home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 May / CMCD0504.ISO / Software / Freeware / Programare / dspack / DSPACK231.exe / {app} / src / DSPack / DSPack.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  2003-02-21  |  212.3 KB  |  5,697 lines

  1.  
  2.     (*********************************************************************
  3.      *  DSPack 2.3                                                       *
  4.      *                                                                   *
  5.      *  home page : http://www.progdigy.com                              *
  6.      *  email     : hgourvest@progdigy.com                               *
  7.      *   Thanks to Michael Andersen. (DSVideoWindowEx)                   *
  8.      *                                                                   *
  9.      *  date      : 21-02-2003                                           *
  10.      *                                                                   *
  11.      *  The contents of this file are used with permission, subject to   *
  12.      *  the Mozilla Public License Version 1.1 (the "License"); you may  *
  13.      *  not use this file except in compliance with the License. You may *
  14.      *  obtain a copy of the License at                                  *
  15.      *  http://www.mozilla.org/MPL/MPL-1.1.html                          *
  16.      *                                                                   *
  17.      *  Software distributed under the License is distributed on an      *
  18.      *  "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or   *
  19.      *  implied. See the License for the specific language governing     *
  20.      *  rights and limitations under the License.                        *
  21.      *                                                                   *
  22.      *********************************************************************)
  23.  
  24. {
  25.   @abstract(DSPack Components.)
  26.   @author(Henri Gourvest: hgourvest@progdigy.com)
  27.   @created(Mar 14, 2002)
  28.   @lastmod(Feb 21, 2003)
  29. }
  30. {$IFDEF VER140} {$WARN SYMBOL_DEPRECATED OFF} {$ENDIF}
  31. {$IFDEF VER150}
  32.   {$WARN SYMBOL_DEPRECATED OFF}
  33.   {$WARN UNSAFE_CODE OFF}
  34.   {$WARN UNSAFE_TYPE OFF}
  35.   {$WARN UNSAFE_CAST OFF}
  36. {$ENDIF}
  37. {$ALIGN ON}
  38. {$MINENUMSIZE 4}
  39.  
  40. unit DSPack;
  41.  
  42. interface
  43. uses
  44.   Windows, Classes, SysUtils, Messages, Graphics, Forms, Controls, ActiveX, DirectShow9,
  45.   DirectDraw, DSUtil, ComCtrls, MMSystem, Math, Consts, ExtCtrls,
  46.   MultiMon, Dialogs, Registry, SyncObjs, Direct3D9, WMF9;
  47.  
  48. const
  49.   { Filter Graph message identifier. }
  50.   WM_GRAPHNOTIFY = WM_APP + 1;
  51.   { Sample Grabber message identifier. }
  52.   WM_CAPTURE_BITMAP = WM_APP + 2;
  53.  
  54. type
  55.  
  56.   { Video mode to use with @link(TVideoWindow). }
  57.   TVideoMode = (
  58.     vmNormal,
  59.     vmVMR
  60.   );
  61.  
  62.   { Graph Mode to use with @link(TFilterGraph).}
  63.   TGraphMode = (
  64.     gmNormal,
  65.     gmCapture,
  66.     gmDVD
  67.   );
  68.  
  69.   { Render device returned by then OnGraphVMRRenderDevice event. }
  70. {$IFDEF VER140}
  71.   TVMRRenderDevice = (
  72.     rdOverlay = 1,
  73.     rdVidMem  = 2,
  74.     rdSysMem  = 4
  75.   );
  76. {$ELSE}
  77.   TVMRRenderDevice = Integer;
  78.   const
  79.     rdOverlay = 1;
  80.     rdVidMem  = 2;
  81.     rdSysMem  = 4;
  82. type
  83. {$ENDIF}
  84.  
  85.   {@exclude}
  86.   TGraphState = (
  87.     gsUninitialized,
  88.     gsStopped,
  89.     gsPaused,
  90.     gsPlaying
  91.   );
  92.  
  93.   { Specifies the seeking capabilities of a media stream. }
  94.   TSeekingCap = (
  95.     CanSeekAbsolute,   // The stream can seek to an absolute position.
  96.     CanSeekForwards,   // The stream can seek forward.
  97.     CanSeekBackwards,  // The stream can seek backward.
  98.     CanGetCurrentPos,  // The stream can report its current position.
  99.     CanGetStopPos,     // The stream can report its stop position.
  100.     CanGetDuration,    // The stream can report its duration.
  101.     CanPlayBackwards,  // The stream can play backward.
  102.     CanDoSegments,     // The stream can do seamless looping (see IMediaSeeking.SetPositions).
  103.     Source             // Reserved.
  104.   );
  105.   { Specifies the seeking capabilities of a media stream. }
  106.   TSeekingCaps = set of TSeekingCap;
  107.  
  108.   { Video Mixer Render Preferences: <br>
  109.     <b>vpForceOffscreen:</b> Indicates that the VMR should use only offscreen surfaces for rendering.<br>
  110.     <b>vpForceOverlays:</b> Indicates that the VMR should fail if no overlay surfaces are available.<br>
  111.     <b>vpForceMixer:</b> Indicates that the VMR must use Mixer when the number of streams is 1.<br>
  112.     <b>vpDoNotRenderColorKeyAndBorder:</b> Indicates that the application is responsible for painting the color keys.<br>
  113.     <b>vpRestrictToInitialMonitor:</b> Indicates that the VMR should output only to the initial monitor.<br>
  114.     <b>vpPreferAGPMemWhenMixing:</b> Indicates that the VMR should attempt to use AGP memory when allocating texture surfaces.}
  115.   TVMRPreference = (
  116.     vpForceOffscreen,
  117.     vpForceOverlays,
  118.     vpForceMixer,
  119.     vpDoNotRenderColorKeyAndBorder,
  120.     vpRestrictToInitialMonitor,
  121.     vpPreferAGPMemWhenMixing
  122.   );
  123.  
  124.   { Pointer to @link(TVMRPreferences).}
  125.   PVMRPreferences = ^TVMRPreferences;
  126.   { Set of @link(TVMRPreference).}
  127.   TVMRPreferences = set of TVMRPreference;
  128.  
  129.   TOnDSEvent                   = procedure(sender: TComponent; Event, Param1, Param2: Integer) of object;
  130.                                                                                                                                    {@exclude}
  131.   TOnGraphBufferingData        = procedure(sender: TObject; Buffering: boolean) of object ;                                        {@exclude}
  132.   TOnGraphComplete             = procedure(sender: TObject; Result: HRESULT; Renderer: IBaseFilter) of object ;                    {@exclude}
  133.   TOnGraphDeviceLost           = procedure(sender: TObject; Device: IUnknown; Removed: Boolean) of object ;                        {@exclude}
  134.   TOnGraphEndOfSegment         = procedure(sender: TObject; StreamTime: TReferenceTime; NumSegment: Cardinal) of object ;         {@exclude}
  135.   TOnDSResult                  = procedure(sender: TObject; Result: HRESULT) of object ;                                           {@exclude}
  136.   TOnGraphFullscreenLost       = procedure(sender: TObject; Renderer: IBaseFilter) of object ;                                     {@exclude}
  137.   TOnGraphOleEvent             = procedure(sender: TObject; String1, String2: WideString) of object ;                              {@exclude}
  138.   TOnGraphOpeningFile          = procedure(sender: TObject; opening: boolean) of object ;                                          {@exclude}
  139.   TOnGraphSNDDevError          = procedure(sender: TObject; OccurWhen: TSndDevErr; ErrorCode: LongWord) of object ;               {@exclude}
  140.   TOnGraphStreamControl        = procedure(sender: TObject; PinSender: IPin; Cookie: LongWord) of object ;                         {@exclude}
  141.   TOnGraphStreamError          = procedure(sender: TObject; Operation: HRESULT; Value: LongWord) of object ;                       {@exclude}
  142.   TOnGraphVideoSizeChanged     = procedure(sender: TObject; Width, height: word) of object ;                                       {@exclude}
  143.   TOnGraphTimeCodeAvailable    = procedure(sender: TObject; From: IBaseFilter; DeviceID: LongWord) of object ;                     {@exclude}
  144.   TOnGraphEXTDeviceModeChange  = procedure(sender: TObject; NewMode, DeviceID: LongWord) of object ;                               {@exclude}
  145.   TOnGraphVMRRenderDevice      = procedure(sender: TObject; RenderDevice: TVMRRenderDevice) of object;
  146.                                                                                                                                    {@exclude}
  147.   TOnDVDAudioStreamChange      = procedure(sender: TObject; stream, lcid: Integer; Lang: string) of object;                        {@exclude}
  148.   TOnDVDCurrentTime            = procedure(sender: TObject; Hours, minutes,seconds,frames,frate : Integer) of object;              {@exclude}
  149.   TOnDVDTitleChange            = procedure(sender: TObject; title: Integer) of object;                                             {@exclude}
  150.   TOnDVDChapterStart           = procedure(sender: TObject; chapter: Integer) of object;                                           {@exclude}
  151.   TOnDVDValidUOPSChange        = procedure(sender: TObject; UOPS: Integer) of object;                                              {@exclude}
  152.   TOnDVDChange                 = procedure(sender: TObject; total,current: Integer) of object;                                     {@exclude}
  153.   TOnDVDStillOn                = procedure(sender: TObject; NoButtonAvailable: boolean; seconds: Integer) of object;               {@exclude}
  154.   TOnDVDSubpictureStreamChange = procedure(sender: TObject; SubNum, lcid: Integer; Lang: string) of object;                        {@exclude}
  155.   TOnDVDPlaybackRateChange     = procedure(sender: TObject; rate:  single) of object;                                              {@exclude}
  156.   TOnDVDParentalLevelChange    = procedure(sender: TObject; level: Integer) of object;                                             {@exclude}
  157.   TOnDVDAnglesAvailable        = procedure(sender: TObject; available: boolean) of object;                                         {@exclude}
  158.   TOnDVDButtonAutoActivated    = procedure(sender: TObject; Button: Cardinal) of object;                                           {@exclude}
  159.   TOnDVDCMD                    = procedure(sender: TObject; CmdID: Cardinal) of object;                                            {@exclude}
  160.   TOnDVDCurrentHMSFTime        = procedure(sender: TObject; HMSFTimeCode: TDVDHMSFTimeCode; TimeCode: TDVDTimeCode) of object;  {@exclude}
  161.   TOnDVDKaraokeMode            = procedure(sender: TObject; Played: boolean) of object;
  162.   {@exclude}
  163.   TOnBuffer = procedure(sender: TObject; SampleTime: Double; pBuffer: Pointer; BufferLen: longint) of object ;
  164.  
  165. // *****************************************************************************
  166. //  IFilter
  167. // *****************************************************************************
  168.  
  169.   {@exclude}
  170.   TFilterOperation = (
  171.     foAdding,    // Before the filter is added to graph.
  172.     foAdded,     // After the filter is added to graph.
  173.     foRemoving,  // Before the filter is removed from graph.
  174.     foRemoved,   // After the filter is removed from graph.
  175.     foRefresh    // Designer notification to Refresh the filter .
  176.   );
  177.  
  178.  
  179.   {@exclude}
  180.   IFilter = interface
  181.   ['{887F94DA-29E9-44C6-B48E-1FBF0FB59878}']
  182.     { Return the IBaseFilter Interface (All DirectShow filters expose this interface). }
  183.     function GetFilter: IBaseFilter;
  184.     { Return the filter name (generally the component name). }
  185.     function GetName: string;
  186.     { Called by the @link(TFilterGraph) component, this method receive notifications
  187.       on what the TFilterGraph is doing. if Operation = foGraphEvent then Param is the
  188.       event code received by the FilterGraph.}
  189.     procedure NotifyFilter(operation: TFilterOperation; Param: integer = 0);
  190.   end;
  191.  
  192.   {@exclude}
  193.   TControlEvent = (
  194.     cePlay,
  195.     cePause,
  196.     ceStop,
  197.     ceFileRendering,
  198.     ceFileRendered,
  199.     ceDVDRendering,
  200.     ceDVDRendered,
  201.     ceActive
  202.   );
  203.  
  204.   {@exclude}
  205.   IEvent = interface
  206.   ['{6C0DCD7B-1A98-44EF-A6D5-E23CBC24E620}']
  207.     { FilterGraph events. }
  208.     procedure GraphEvent(Event, Param1, Param2: integer);
  209.     { Control Events. }
  210.     procedure ControlEvent(Event: TControlEvent; Param: integer = 0);
  211.   end;
  212.  
  213.  
  214.  
  215. // *****************************************************************************
  216. //  TFilterGraph
  217. // *****************************************************************************
  218.  
  219.   { This component is the central component in DirectShow, the Filter Graph
  220.     handle synchronization, event notification, and other aspects of the
  221.     controlling the filter graph. }
  222.   TFilterGraph = class(TComponent)
  223.   private
  224.     FActive     : boolean;
  225.     FAutoCreate : boolean;
  226.     FHandle     : THandle; // to capture events
  227.     FMode       : TGraphMode;
  228.  
  229.     FFilters: TInterfaceList;
  230.     FGraphEvents: TInterfaceList;
  231.  
  232.     // builders
  233.     FFilterGraph  : IGraphBuilder;
  234.     FCaptureGraph : ICaptureGraphBuilder2;
  235.     FDVDGraph     : IDvdGraphBuilder;
  236.  
  237.     // events interface
  238.     FMediaEventEx : IMediaEventEx;
  239.  
  240.     // Graphedit
  241.     FGraphEdit    : boolean;
  242.     FGraphEditID  : Integer;
  243.  
  244.     // Log File
  245.     FLogFileName: String;
  246.     FLogFile: TFileStream;
  247.  
  248.     FOnActivate: TNotifyEvent;
  249.  
  250.     // All Events Code
  251.     FOnDSEvent : TOnDSEvent;
  252.     // Generic Graph Events
  253.     FOnGraphBufferingData           : TOnGraphBufferingData;
  254.     FOnGraphClockChanged            : TNotifyEvent;
  255.     FOnGraphComplete                : TOnGraphComplete;
  256.     FOnGraphDeviceLost              : TOnGraphDeviceLost;
  257.     FOnGraphEndOfSegment            : TOnGraphEndOfSegment;
  258.     FOnGraphErrorStillPlaying       : TOnDSResult;
  259.     FOnGraphErrorAbort              : TOnDSResult;
  260.     FOnGraphFullscreenLost          : TOnGraphFullscreenLost;
  261.     FOnGraphChanged                 : TNotifyEvent;
  262.     FOnGraphOleEvent                : TOnGraphOleEvent;
  263.     FOnGraphOpeningFile             : TOnGraphOpeningFile;
  264.     FOnGraphPaletteChanged          : TNotifyEvent;
  265.     FOnGraphPaused                  : TOnDSResult;
  266.     FOnGraphQualityChange           : TNotifyEvent;
  267.     FOnGraphSNDDevInError           : TOnGraphSNDDevError;
  268.     FOnGraphSNDDevOutError          : TOnGraphSNDDevError;
  269.     FOnGraphStepComplete            : TNotifyEvent;
  270.     FOnGraphStreamControlStarted    : TOnGraphStreamControl;
  271.     FOnGraphStreamControlStopped    : TOnGraphStreamControl;
  272.     FOnGraphStreamErrorStillPlaying : TOnGraphStreamError;
  273.     FOnGraphStreamErrorStopped      : TOnGraphStreamError;
  274.     FOnGraphUserAbort               : TNotifyEvent;
  275.     FOnGraphVideoSizeChanged        : TOnGraphVideoSizeChanged;
  276.     FOnGraphTimeCodeAvailable       : TOnGraphTimeCodeAvailable;
  277.     FOnGraphEXTDeviceModeChange     : TOnGraphEXTDeviceModeChange;
  278.     FOnGraphClockUnset              : TNotifyEvent;
  279.     FOnGraphVMRRenderDevice         : TOnGraphVMRRenderDevice;
  280.  
  281.     FOnDVDAudioStreamChange       : TOnDVDAudioStreamChange;
  282.     FOnDVDCurrentTime             : TOnDVDCurrentTime;
  283.     FOnDVDTitleChange             : TOnDVDTitleChange;
  284.     FOnDVDChapterStart            : TOnDVDChapterStart;
  285.     FOnDVDAngleChange             : TOnDVDChange;
  286.     FOnDVDValidUOPSChange         : TOnDVDValidUOPSChange;
  287.     FOnDVDButtonChange            : TOnDVDChange;
  288.     FOnDVDChapterAutoStop         : TNotifyEvent;
  289.     FOnDVDStillOn                 : TOnDVDStillOn;
  290.     FOnDVDStillOff                : TNotifyEvent;
  291.     FOnDVDSubpictureStreamChange  : TOnDVDSubpictureStreamChange;
  292.     FOnDVDNoFP_PGC                : TNotifyEvent;
  293.     FOnDVDPlaybackRateChange      : TOnDVDPlaybackRateChange;
  294.     FOnDVDParentalLevelChange     : TOnDVDParentalLevelChange;
  295.     FOnDVDPlaybackStopped         : TNotifyEvent;
  296.     FOnDVDAnglesAvailable         : TOnDVDAnglesAvailable;
  297.     FOnDVDPlayPeriodAutoStop      : TNotifyEvent;
  298.     FOnDVDButtonAutoActivated     : TOnDVDButtonAutoActivated;
  299.     FOnDVDCMDStart                : TOnDVDCMD;
  300.     FOnDVDCMDEnd                  : TOnDVDCMD;
  301.     FOnDVDDiscEjected             : TNotifyEvent;
  302.     FOnDVDDiscInserted            : TNotifyEvent;
  303.     FOnDVDCurrentHMSFTime         : TOnDVDCurrentHMSFTime;
  304.     FOnDVDKaraokeMode             : TOnDVDKaraokeMode;
  305.     // DVD Warning
  306.     FOnDVDWarningInvalidDVD1_0Disc  : TNotifyEvent;//=1,
  307.     FOnDVDWarningFormatNotSupported : TNotifyEvent;//=2,
  308.     FOnDVDWarningIllegalNavCommand  : TNotifyEvent;//=3
  309.     FOnDVDWarningOpen               : TNotifyEvent;//=4
  310.     FOnDVDWarningSeek               : TNotifyEvent;//=5
  311.     FOnDVDWarningRead               : TNotifyEvent;//=6
  312.     // DVDDomain
  313.     FOnDVDDomainFirstPlay         : TNotifyEvent;
  314.     FOnDVDDomainVideoManagerMenu  : TNotifyEvent;
  315.     FOnDVDDomainVideoTitleSetMenu : TNotifyEvent;
  316.     FOnDVDDomainTitle             : TNotifyEvent;
  317.     FOnDVDDomainStop              : TNotifyEvent;
  318.     // DVDError
  319.     FOnDVDErrorUnexpected                          : TNotifyEvent;
  320.     FOnDVDErrorCopyProtectFail                     : TNotifyEvent;
  321.     FOnDVDErrorInvalidDVD1_0Disc                   : TNotifyEvent;
  322.     FOnDVDErrorInvalidDiscRegion                   : TNotifyEvent;
  323.     FOnDVDErrorLowParentalLevel                    : TNotifyEvent;
  324.     FOnDVDErrorMacrovisionFail                     : TNotifyEvent;
  325.     FOnDVDErrorIncompatibleSystemAndDecoderRegions : TNotifyEvent;
  326.     FOnDVDErrorIncompatibleDiscAndDecoderRegions   : TNotifyEvent;
  327.  
  328.     procedure HandleEvents;
  329.     procedure WndProc(var Msg: TMessage);
  330.     procedure SetActive(Activate: boolean);
  331.     procedure SetGraphMode(Mode: TGraphMode);
  332.     procedure SetGraphEdit(enable: boolean);
  333.     procedure ClearOwnFilters;
  334.     procedure AddOwnFilters;
  335.     procedure GraphEvents(Event, Param1, Param2: integer);
  336.     procedure ControlEvents(Event: TControlEvent; Param: integer = 0);
  337.     procedure SetLogFile(FileName: String);
  338.     function GetState: TGraphState;
  339.     function GetVolume: integer;
  340.     procedure SetVolume(Volume: Integer);
  341.     function GetBalance: integer;
  342.     procedure SetBalance(Balance: integer);
  343.     function GetSeekCaps: TSeekingCaps;
  344.     procedure SetRate(Rate: double);
  345.     function GetRate: double;
  346.     function GetDuration: integer;
  347.   protected
  348.     {@exclude}
  349.     procedure DoEvent(Event, Param1, Param2: Integer); virtual;
  350.     {@exclude}
  351.     procedure InsertFilter(AFilter: IFilter);
  352.     {@exclude}
  353.     procedure RemoveFilter(AFilter: IFilter);
  354.     {@exclude}
  355.     procedure InsertEventNotifier(AEvent: IEvent);
  356.     {@exclude}
  357.     procedure RemoveEventNotifier(AEvent: IEvent);
  358.   public
  359.     { Retrieve the total duration of a stream. }
  360.     property Duration: Integer read GetDuration;
  361.     { Retrieve/Set the rate. }
  362.     property Rate: Double read GetRate write SetRate;
  363.     { Retrieve the seeking capabilities. }
  364.     property SeekCapabilities: TSeekingCaps read GetSeekCaps;
  365.     { The volume balance. }
  366.     property Balance: integer read GetBalance write SetBalance;
  367.     { The volume. }
  368.     property Volume: integer read GetVolume write SetVolume;
  369.     { Current state of the filter graph. }
  370.     property State: TGraphState read GetState;
  371.     { TFilterGraph constructor. }
  372.     constructor Create(AOwner: TComponent); override;
  373.     { TFilterGraph destructor. }
  374.     destructor Destroy; override;
  375.     { @exclude}
  376.     procedure Loaded; override;
  377.     { Retrieve an Interface from the current Graph.<br>
  378.       <b>ex: </b> (FilterGraph <b>as</b> IGraphBuilder).RenderFile('C:\speedis.avi', <b>nil</b>);<br>
  379.       <b>Remark: </b> The interfaces you can Query depend of the @link(Mode) you
  380.       have defined.<br>
  381.       <b>gmNormal: </b>IAMGraphStreams, IAMStats, IBasicAudio, IBasicVideo,
  382.                        IBasicVideo2, IFilterChain, IFilterGraph, IFilterGraph2,
  383.                        IFilterMapper2, IGraphBuilder, IGraphConfig, IGraphVersion,
  384.                        IMediaControl, IMediaEvent, IMediaEventEx, IMediaEventSink,
  385.                        IMediaFilter, IMediaPosition, IMediaSeeking, IQueueCommand,
  386.                        IRegisterServiceProvider, IResourceManager, IServiceProvider,
  387.                        IVideoFrameStep, IVideoWindow. <br>
  388.       <b>gmCapture: </b> all gmNormal interfaces and ICaptureGraphBuilder2.<br>
  389.       <b>gmDVD: </b> all gmNormal interfaces and IDvdGraphBuilder, IDvdControl2,
  390.                      IDvdInfo2, IAMLine21Decoder.}
  391.     function QueryInterface(const IID: TGUID; out Obj): HResult; override; stdcall;
  392.     { The Run method runs all the filters in the filter graph. While the graph
  393.       is running, data moves through the graph and is rendered. }
  394.     function Play: boolean;
  395.     { The Pause method pauses all the filters in the filter graph. }
  396.     function Pause: boolean;
  397.     { The Stop method stops all the filters in the graph. }
  398.     function Stop: boolean;
  399.     { This method disconnect all pins.}
  400.     procedure DisconnectFilters;
  401.     { Disconnect and remove all filters from the filter graph excepting the custom components. }
  402.     procedure ClearGraph;
  403.     { Render a single file. }
  404.     function RenderFile(FileName: WideString): HRESULT;
  405.     function RenderFileEx(FileName: WideString): HRESULT;
  406.     { Render a DVD Video Volume or a File Name if specified. }
  407.     function RenderDVD(out status: TAMDVDRenderStatus;
  408.       FileName: WideString = ''; Mode: Integer = AM_DVD_HWDEC_PREFER): HRESULT;
  409.     { Save the current state and position of a DVD movie to a file.<br>
  410.       See also: @link(DVDRestoreBookmark).}
  411.     procedure DVDSaveBookmark(BookMarkFile: WideString);
  412.     { Restore the State and position of a DVD movie saved by @link(DVDSaveBookmark).}
  413.     procedure DVDRestoreBookmark(BookMarkFile: WideString);
  414.   published
  415.  
  416.     { Specify a File Name to save the Filter Graph Log. }
  417.     property LogFile: String read FLogFileName write SetLogFile;
  418.  
  419.     { Activate the Filter Graph.}
  420.     property Active: boolean read FActive write SetActive default False;
  421.  
  422.     { Auto-Activate the Filter Graph when component is created.}
  423.     property AutoCreate: boolean read FAutoCreate write FAutoCreate default False;
  424.  
  425.     { There is 3 modes: gmNormal, gmCapture and gmDVD. <br>
  426.       See also: @link(GraphInterFace).}
  427.     property Mode: TGraphMode read FMode write SetGraphMode default gmNormal;
  428.  
  429.     { if true you can use GraphEdit application to connect with the Filter Graph.}
  430.     property GraphEdit: boolean read FGraphEdit write SetGraphEdit;
  431.  
  432.     // -------------------------------------------------------------------------
  433.     // Events
  434.     // -------------------------------------------------------------------------
  435.  
  436.     property OnActivate: TNotifyEvent read FOnActivate write FOnActivate;
  437.  
  438.     { Generic Filter Graph event.<br>
  439.         <b>Event:</b> message sent.<br>
  440.         <b>Param1:</b> first message parameter.<br>
  441.         <b>Param2:</b> second message parameter.}
  442.     property OnDSEvent: TOnDSEvent read FOnDSEvent write FOnDSEvent;
  443.  
  444.     { The graph is buffering data, or has stopped buffering data.
  445.       A filter can send this event if it needs to buffer data from an external
  446.       source. (for example, it might be loading data from a network.)
  447.       The application can use this event to adjust its user interface.<br>
  448.       <b>buffering:</b> TRUE if the graph is starting to buffer, or FALSE if
  449.       the graph has stopped buffering. }
  450.     property OnGraphBufferingData: TOnGraphBufferingData read FOnGraphBufferingData write FOnGraphBufferingData;
  451.  
  452.     { The reference clock has changed. The filter graph manager sends this event
  453.       when its IMediaFilter.SetSyncSource method is called.}
  454.     property OnGraphClockChanged: TNotifyEvent read FOnGraphClockChanged write FOnGraphClockChanged;
  455.  
  456.     { All data from a particular stream has been rendered.
  457.       By default, the filter graph manager does not forward this event to the
  458.       application. However, after all the streams in the graph report EC_COMPLETE,
  459.       the filter graph manager posts a separate EC_COMPLETE event to the application.<br>
  460.         <b>Result:</b> HRESULT value; can be S_OK.<br>
  461.         <b>Renderer:</b> nil, or a reference to the renderer's IBaseFilter interface.}
  462.     property OnGraphComplete: TOnGraphComplete read FOnGraphComplete write FOnGraphComplete;
  463.  
  464.     { A Plug and Play device was removed or became available again. When the
  465.       device becomes available again, the previous state of the device filter is
  466.       no longer valid. The application must rebuild the graph in order to use the device.<br>
  467.         <b>Device:</b> IUnknown interface of the filter that represents the device.<br>
  468.         <b>Removed:</b> True if the device was removed, or False if the device is available again.}
  469.     property OnGraphDeviceLost: TOnGraphDeviceLost read FOnGraphDeviceLost write FOnGraphDeviceLost;
  470.  
  471.     { The end of a segment was reached.
  472.       This event code supports seamless looping. When a call to the IMediaSeeking.SetPositions
  473.       method includes the AM_SEEKING_Segment flag, the source filter sends this
  474.       event code instead of calling IPin.EndOfStream.<br>
  475.         <b>StreamTime:</b> TREFERENCE_TIME value that specifies the accumulated stream time since the start of the segment.<br>
  476.         <b>NumSegment:</b> Cardinal value indicating the segment number (zero-based).}
  477.     property OnGraphEndOfSegment: TOnGraphEndOfSegment read FOnGraphEndOfSegment write FOnGraphEndOfSegment;
  478.  
  479.     { An asynchronous command to run the graph has failed.
  480.       if the filter graph manager issues an asynchronous run command that fails,
  481.       it sends this event to the application. The graph remains in a running state.
  482.       The state of the underlying filters is indeterminate. Some filters might be
  483.       running, others might not.<br>
  484.         <b>Result:</b> value of the operation that failed.}
  485.     property OnGraphErrorStillPlaying: TOnDSResult read FOnGraphErrorStillPlaying write FOnGraphErrorStillPlaying;
  486.  
  487.     { An operation was aborted because of an error.<br>
  488.         <b>Result:</b> value of the operation that failed.}
  489.     property OnGraphErrorAbort: TOnDSResult read FOnGraphErrorAbort write FOnGraphErrorAbort;
  490.  
  491.     { The video renderer is switching out of full-screen mode.
  492.       When the Full Screen Renderer loses activation, it sends this event. When
  493.       another video renderer switches out of full-screen mode, the filter graph
  494.       manager sends this event, in response to an EC_ACTIVATE event from the renderer.<br>
  495.         <b>Renderer:</b> the video renderer's IBaseFilter interface, or nil.}
  496.     property OnGraphFullscreenLost: TOnGraphFullscreenLost read FOnGraphFullscreenLost write FOnGraphFullscreenLost;
  497.  
  498.     { The filter graph has changed.
  499.       This event code is intended for debugging. It is not sent for all graph changes.}
  500.     property OnGraphChanged: TNotifyEvent read FOnGraphChanged write FOnGraphChanged;
  501.  
  502.     { A filter is passing a text string to the application.
  503.       By convention, the first parameter contains type information (for example, Text)
  504.       and the second parameter contains the text string.<br>
  505.         <b>String1, String2:</b> Wide Strings}
  506.     property OnGraphOleEvent: TOnGraphOleEvent read FOnGraphOleEvent write FOnGraphOleEvent;
  507.  
  508.     { The graph is opening a file, or has finished opening a file.
  509.       A filter can send this event if it spends significant time opening a file.
  510.       (for example, the file might be located on a network.) The application can use
  511.       this event to adjust its user interface.<br>
  512.         <b>opening:</b> TRUE if the graph is starting to open a file, or FALSE
  513.                         if the graph is no longer opening the file.}
  514.     property OnGraphOpeningFile: TOnGraphOpeningFile read FOnGraphOpeningFile write FOnGraphOpeningFile;
  515.  
  516.     {  The video palette has changed.
  517.        Video renderers send this event if they detect a palette change in the stream.}
  518.     property OnGraphPaletteChanged: TNotifyEvent read FOnGraphPaletteChanged write FOnGraphPaletteChanged;
  519.  
  520.     { A pause request has completed.
  521.       The filter graph manager sends this event when it completes an asynchronous pause command.<br>
  522.         <b>Result:</b> value that indicates the result of the transition. if the
  523.                        value is S_OK, the filter graph is now in a paused state.}
  524.     property OnGraphPaused: TOnDSResult read FOnGraphPaused write FOnGraphPaused;
  525.  
  526.     { The graph is dropping samples, for quality control.
  527.       A filter sends this event if it drops samples in response to a quality control
  528.       message. It sends the event only when it adjusts the quality level, not for each
  529.       sample that it drops. }
  530.     property OnGraphQualityChange: TNotifyEvent read FOnGraphQualityChange write FOnGraphQualityChange;
  531.  
  532.     { An audio device error occurred on an input pin.<br>
  533.         <b>OccurWhen:</b> value from the TSNDDEV_ERR enumerated type, indicating how the device was being accessed when the failure occurred.<br>
  534.         <b>ErrorCode:</b> value indicating the error returned from the sound device call.}
  535.     property OnGraphSNDDevInError: TOnGraphSNDDevError read FOnGraphSNDDevInError write FOnGraphSNDDevInError;
  536.  
  537.     { An audio device error occurred on an output pin.<br>
  538.         <b>OccurWhen:</b> value from the TSNDDEV_ERR enumerated type, indicating how the device was being accessed when the failure occurred.<br>
  539.         <b>ErrorCode:</b> value indicating the error returned from the sound device call.}
  540.     property OnGraphSNDDevOutError: TOnGraphSNDDevError read FOnGraphSNDDevOutError write FOnGraphSNDDevOutError;
  541.  
  542.     { A filter has completed frame stepping.
  543.       The filter graph manager pauses the graph and passes the event to the application.}
  544.     property OnGraphStepComplete: TNotifyEvent read FOnGraphStepComplete write FOnGraphStepComplete;
  545.  
  546.     { A stream-control start command has taken effect.
  547.       Filters send this event in response to the IAMStreamControl.StartAt method.
  548.       This method specifies a reference time for a pin to begin streaming.
  549.       When streaming does begin, the filter sends this event.<br>
  550.         <b>PinSender</b> parameter specifies the pin that executes the start command.
  551.                          Depending on the implementation, it might not be the pin that
  552.                          received the StartAt call.<br>
  553.         <b>Cookie</b> parameter is specified by the application in the StartAt method.
  554.                       This parameter enables the application to track multiple calls to the method.}
  555.     property OnGraphStreamControlStarted: TOnGraphStreamControl read FOnGraphStreamControlStarted  write FOnGraphStreamControlStarted;
  556.  
  557.     { A stream-control start command has taken effect.
  558.       Filters send this event in response to the IAMStreamControl.StopAt method.
  559.       This method specifies a reference time for a pin to stop streaming.
  560.       When streaming does halt, the filter sends this event.<br>
  561.         <b>PinSender</b> parameter specifies the pin that executes the stop command.
  562.                          Depending on the implementation, it might not be the pin
  563.                          that received the StopAt call.<br>
  564.         <b>Cookie</b> parameter is specified by the application in the StopAt method.
  565.                       This parameter enables the application to track multiple calls to the method.}
  566.     property OnGraphStreamControlStopped: TOnGraphStreamControl read FOnGraphStreamControlStopped write FOnGraphStreamControlStopped;
  567.  
  568.     { An error occurred in a stream, but the stream is still playing.<br>
  569.         <b>Operation:</b> HRESULT of the operation that failed.<br>
  570.         <b>Value:</b> LongWord value, generally zero. }
  571.     property OnGraphStreamErrorStillPlaying : TOnGraphStreamError read FOnGraphStreamErrorStillPlaying write FOnGraphStreamErrorStillPlaying;
  572.  
  573.     { A stream has stopped because of an error.<br>
  574.         <b>Operation:</b> HRESULT of the operation that failed.<br>
  575.         <b>Value:</b> LongWord value, generally zero. }
  576.     property OnGraphStreamErrorStopped: TOnGraphStreamError read FOnGraphStreamErrorStopped write FOnGraphStreamErrorStopped;
  577.  
  578.     { The user has terminated playback.<br>
  579.       This event code signals that the user has terminated normal graph playback.
  580.       for example, video renderers send this event if the user closes the video window.<br>
  581.       After sending this event, the filter should reject all samples and not send
  582.       any EC_REPAINT events, until the filter stops and is reset.}
  583.     property OnGraphUserAbort: TNotifyEvent read FOnGraphUserAbort write FOnGraphUserAbort;
  584.  
  585.     { The native video size has changed.<br>
  586.         <b>width:</b> new width, in pixels.<br>
  587.         <b>height:</b> new height, in pixels. }
  588.     property OnGraphVideoSizeChanged: TOnGraphVideoSizeChanged read FOnGraphVideoSizeChanged write FOnGraphVideoSizeChanged;
  589.  
  590.     { Sent by filter supporting timecode.<br>
  591.         <b>From:</b> sending object.<br>
  592.         <b>DeviceID:</b> device ID of the sending object}
  593.     property OnGraphTimeCodeAvailable: TOnGraphTimeCodeAvailable read FOnGraphTimeCodeAvailable write FOnGraphTimeCodeAvailable;
  594.  
  595.     { Sent by filter supporting IAMExtDevice.<br>
  596.         <b>NewMode:</b> the new mode<br>
  597.         <b>DeviceID:</b> the device ID of the sending object}
  598.     property OnGraphEXTDeviceModeChange: TOnGraphEXTDeviceModeChange read FOnGraphEXTDeviceModeChange write FOnGraphEXTDeviceModeChange;
  599.  
  600.     { The clock provider was disconnected.<br>
  601.       KSProxy signals this event when the pin of a clock-providing filter is disconnected.}
  602.     property OnGraphClockUnset: TNotifyEvent read FOnGraphClockUnset write FOnGraphClockUnset;
  603.  
  604.     { Identifies the type of rendering mechanism the VMR is using to display video.}
  605.     property OnGraphVMRRenderDevice: TOnGraphVMRRenderDevice read FOnGraphVMRRenderDevice write FOnGraphVMRRenderDevice;
  606.  
  607.     { Signals that the current audio stream number changed for the main title.<br>
  608.       The current audio stream can change automatically with a navigation command
  609.       authored on the disc as well as through application control by using the IDvdControl2 interface.<br>
  610.       <b>stream:</b> value indicating the new user audio stream number. Audio stream numbers
  611.         range from 0 to 7. Stream $FFFFFFFF indicates that no stream is selected.<br>
  612.       <b>lcid:</b> Language identifier.<br>
  613.       <b>Lang:</b> Language string. }
  614.     property OnDVDAudioStreamChange: TOnDVDAudioStreamChange read FOnDVDAudioStreamChange write FOnDVDAudioStreamChange;
  615.  
  616.     { Deprecated, use @link(OnDVDCurrentHMSFTime) instead.<br>
  617.       Signals the beginning of every video object unit (VOBU), a video segment
  618.       which is 0.4 to 1.0 seconds in length.<br> }
  619.     property OnDVDCurrentTime: TOnDVDCurrentTime read FOnDVDCurrentTime write FOnDVDCurrentTime;
  620.  
  621.     { Indicates when the current title number changes.<br>
  622.       Title numbers range from 1 to 99. This number indicates the TTN, which is
  623.       the title number with respect to the whole disc, not the VTS_TTN which is
  624.       the title number with respect to just a current VTS.<br>
  625.       <b>Title:</b> value indicating the new title number.}
  626.     property OnDVDTitleChange: TOnDVDTitleChange read FOnDVDTitleChange write FOnDVDTitleChange;
  627.  
  628.     { Signals that the DVD player started playback of a new program in the
  629.       DVD_DOMAIN_Title domain.<br>
  630.       Only simple linear movies signal this event.<br>
  631.       <b>chapter:</b> value indicating the new chapter (program) number.}
  632.     property OnDVDChapterStart: TOnDVDChapterStart read FOnDVDChapterStart write FOnDVDChapterStart;
  633.  
  634.     { Signals that either the number of available angles changed or that the
  635.       current angle number changed.<br>
  636.       Angle numbers range from 1 to 9. The current angle number can change
  637.       automatically with a navigation command authored on the disc as well as
  638.       through application control by using the IDvdControl2 interface.<br>
  639.       <b>total:</b> value indicating the number of available angles. When the
  640.          number of available angles is 1, the current video is not multiangle.<br>
  641.       <b>current:</b> value indicating the current angle number.}
  642.     property OnDVDAngleChange: TOnDVDChange read FOnDVDAngleChange write FOnDVDAngleChange;
  643.  
  644.     { Signals that the available set of IDvdControl2 interface methods has changed.<br>
  645.       <b>UOPS:</b> value representing a ULONG whose bits indicate which IDvdControl2
  646.       commands the DVD disc explicitly disabled. }
  647.     property OnDVDValidUOPSChange: TOnDVDValidUOPSChange read FOnDVDValidUOPSChange write FOnDVDValidUOPSChange;
  648.  
  649.     { Signals that either the number of available buttons changed or that the
  650.       currently selected button number changed.<br>
  651.       This event can signal any of the available button numbers. These numbers
  652.       do not always correspond to button numbers used for
  653.       IDvdControl2.SelectAndActivateButton because that method can activate only
  654.       a subset of buttons.<br>
  655.       <b>total:</b> value indicating the number of available buttons.<br>
  656.       <b>current:</b> value indicating the currently selected button number.
  657.         Selected button number zero implies that no button is selected.}
  658.     property OnDVDButtonChange: TOnDVDChange read FOnDVDButtonChange write FOnDVDButtonChange;
  659.  
  660.     { Indicates that playback stopped as the result of a call to the
  661.       IDvdControl2.PlayChaptersAutoStop method.}
  662.     property OnDVDChapterAutoStop: TNotifyEvent read FOnDVDChapterAutoStop write FOnDVDChapterAutoStop;
  663.  
  664.     { Signals the beginning of any still (PGC, Cell, or VOBU).
  665.       All combinations of buttons and still are possible (buttons on with still
  666.       on, buttons on with still off, button off with still on, button off with still off).<br>
  667.       <b>NoButtonAvailable</b>: Boolean value indicating whether buttons are
  668.       available. False indicates buttons are available so the IDvdControl2.StillOff
  669.       method won't work. True indicates no buttons are available, so IDvdControl2.StillOff will work.<br>
  670.       <b>seconds</b>: value indicating the number of seconds the still will last.
  671.       $FFFFFFFF indicates an infinite still, meaning wait until the user presses
  672.       a button or until the application calls IDvdControl2.StillOff.}
  673.     property OnDVDStillOn: TOnDVDStillOn read FOnDVDStillOn write FOnDVDStillOn;
  674.  
  675.     { Signals the end of any still (PGC, Cell, or VOBU).<br>
  676.       This event indicates that any currently active still has been released.}
  677.     property OnDVDStillOff: TNotifyEvent read FOnDVDStillOff write FOnDVDStillOff;
  678.  
  679.     { Signals that the current subpicture stream number changed for the main title.<br>
  680.       The subpicture can change automatically with a navigation command authored
  681.       on disc as well as through application control using IDvdControl2.<br>
  682.       <b>SubNum:</b> value indicating the new user subpicture stream number.
  683.         Subpicture stream numbers range from 0 to 31. Stream $FFFFFFFF indicates
  684.         that no stream is selected.<br>
  685.       <b>lcid:</b> Language identifier.<br>
  686.       <b>Lang:</b> Language string.}
  687.     property OnDVDSubpictureStreamChange: TOnDVDSubpictureStreamChange read FOnDVDSubpictureStreamChange write FOnDVDSubpictureStreamChange;
  688.  
  689.     { Signals that the DVD disc does not have a FP_PGC (First Play Program Chain)
  690.       and that the DVD Navigator will not automatically load any PGC and start playback.}
  691.     property OnDVDNoFP_PGC: TNotifyEvent read FOnDVDNoFP_PGC write FOnDVDNoFP_PGC;
  692.  
  693.     { Signals that a rate change in the playback has been initiated.
  694.       <b>rate:</b> indicate the new playback rate. rate < 0 indicates reverse playback
  695.       mode. rate > 0 indicates forward playback mode.}
  696.     property OnDVDPlaybackRateChange: TOnDVDPlaybackRateChange read FOnDVDPlaybackRateChange write FOnDVDPlaybackRateChange;
  697.  
  698.     { Signals that the parental level of the authored content is about to change.<br>
  699.       The DVD Navigator source filter does not currently support "on the fly"
  700.       parental level changes in response to SetTmpPML commands on a DVD disc.<br>
  701.       <b>level:</b> value representing the new parental level set in the player.}
  702.     property OnDVDParentalLevelChange: TOnDVDParentalLevelChange read FOnDVDParentalLevelChange write FOnDVDParentalLevelChange;
  703.  
  704.     { Indicates that playback has been stopped. The DVD Navigator has completed
  705.       playback of the title or chapter and did not find any other branching
  706.       instruction for subsequent playback. }
  707.     property OnDVDPlaybackStopped: TNotifyEvent read FOnDVDPlaybackStopped write FOnDVDPlaybackStopped;
  708.  
  709.     { Indicates whether an angle block is being played and angle changes can be performed.<br>
  710.       Angle changes are not restricted to angle blocks and the manifestation of
  711.       the angle change can be seen only in an angle block.<br>
  712.       <b>available:</b> Boolean value that indicates if an angle block is being
  713.       played back. False indicates that playback is not in an angle block and
  714.       angles are not available, True indicates that an angle block is being played
  715.       back and angle changes can be performed.}
  716.     property OnDVDAnglesAvailable: TOnDVDAnglesAvailable read FOnDVDAnglesAvailable write FOnDVDAnglesAvailable;
  717.  
  718.     { Indicates that the Navigator has finished playing the segment specified
  719.       in a call to PlayPeriodInTitleAutoStop.}
  720.     property OnDVDPlayPeriodAutoStop: TNotifyEvent read FOnDVDPlayPeriodAutoStop write FOnDVDPlayPeriodAutoStop;
  721.  
  722.     { Signals that a menu button has been automatically activated per instructions
  723.       on the disc. This occurs when a menu times out and the disc has specified a
  724.       button to be automatically activated.<br>
  725.       <b>Button</b>: value indicating the button that was activated.}
  726.     property OnDVDButtonAutoActivated: TOnDVDButtonAutoActivated read FOnDVDButtonAutoActivated write FOnDVDButtonAutoActivated;
  727.  
  728.     { Signals that a particular command has begun.<br>
  729.       <b>CmdID:</b> The Command ID and the HRESULT return value.}
  730.     property OnDVDCMDStart: TOnDVDCMD read FOnDVDCMDStart Write FOnDVDCMDStart;
  731.  
  732.     { Signals that a particular command has completed.<br>
  733.       <b>CmdID</b> The Command ID and the completion result.}
  734.     property OnDVDCMDEnd: TOnDVDCMD read FOnDVDCMDEnd Write FOnDVDCMDEnd;
  735.  
  736.     { Signals that a disc was ejected.<br>
  737.       Playback automatically stops when a disc is ejected. The application does
  738.       not have to take any special action in response to this event.}
  739.     property OnDVDDiscEjected: TNotifyEvent read FOnDVDDiscEjected Write FOnDVDDiscEjected;
  740.  
  741.     { Signals that a disc was inserted into the drive.<br>
  742.       Playback automatically begins when a disc is inserted. The application does
  743.       not have to take any special action in response to this event.}
  744.     property OnDVDDiscInserted: TNotifyEvent read FOnDVDDiscInserted write FOnDVDDiscInserted;
  745.  
  746.     { Signals the current time, in DVD_HMSF_TIMECODE format, relative to the start
  747.       of the title. This event is triggered at the beginning of every VOBU, which
  748.       occurs every 0.4 to 1.0 seconds.<br>
  749.       The TDVD_HMSF_TIMECODE format is intended to replace the old BCD format that
  750.       is returned in OnDVDCurrentTime events. The HMSF timecodes are easier to
  751.       work with. To have the Navigator send EC_DVD_CURRENT_HMSF_TIME events instead
  752.       of EC_DVD_CURRENT_TIME events, an application must call
  753.       IDvdControl2.SetOption(DVD_HMSF_TimeCodeEvents, TRUE). When this flag is set,
  754.       the Navigator will also expect all time parameters in the IDvdControl2 and
  755.       IDvdInfo2 methods to be passed as TDVD_HMSF_TIMECODEs.<br>
  756.       <b>HMSFTimeCode:</b> HMS Time code structure.<br>
  757.       <b>TimeCode:</b> old time format, do not use. }
  758.     property OnDVDCurrentHMSFTime: TOnDVDCurrentHMSFTime read FOnDVDCurrentHMSFTime write FOnDVDCurrentHMSFTime;
  759.  
  760.     { Indicates that the Navigator has either begun playing or finished playing karaoke data.<br>
  761.       The DVD player signals this event whenever it changes domains.<br>
  762.       <b>Played:</b> TRUE means that a karaoke track is being played and FALSE means
  763.         that no karaoke data is being played. }
  764.     property OnDVDKaraokeMode: TOnDVDKaraokeMode read FOnDVDKaraokeMode write FOnDVDKaraokeMode;
  765.  
  766.     { Performing default initialization of a DVD disc.}
  767.     property OnDVDDomainFirstPlay: TNotifyEvent read FOnDVDDomainFirstPlay write FOnDVDDomainFirstPlay;
  768.  
  769.     { Displaying menus for whole disc. }
  770.     property OnDVDDomainVideoManagerMenu: TNotifyEvent read FOnDVDDomainVideoManagerMenu write FOnDVDDomainVideoManagerMenu;
  771.  
  772.     { Displaying menus for current title set. }
  773.     property OnDVDDomainVideoTitleSetMenu: TNotifyEvent read FOnDVDDomainVideoTitleSetMenu write FOnDVDDomainVideoTitleSetMenu;
  774.  
  775.     { Displaying the current title. }
  776.     property OnDVDDomainTitle: TNotifyEvent read FOnDVDDomainTitle write FOnDVDDomainTitle;
  777.  
  778.     { The DVD Navigator is in the DVD Stop domain.}
  779.     property OnDVDDomainStop: TNotifyEvent read FOnDVDDomainStop write FOnDVDDomainStop;
  780.  
  781.     { Something unexpected happened; perhaps content is authored incorrectly.
  782.       Playback is stopped.}
  783.     property OnDVDErrorUnexpected: TNotifyEvent read FOnDVDErrorUnexpected write FOnDVDErrorUnexpected;
  784.  
  785.     { Key exchange for DVD copy protection failed. Playback is stopped. }
  786.     property OnDVDErrorCopyProtectFail: TNotifyEvent read FOnDVDErrorCopyProtectFail write FOnDVDErrorCopyProtectFail;
  787.  
  788.     { DVD-Video disc is authored incorrectly for specification version 1.x.
  789.       Playback is stopped.}
  790.     property OnDVDErrorInvalidDVD1_0Disc: TNotifyEvent read FOnDVDErrorInvalidDVD1_0Disc write FOnDVDErrorInvalidDVD1_0Disc;
  791.  
  792.     { DVD-Video disc cannot be played because the disc is not authored to play in
  793.       the system region. }
  794.     property OnDVDErrorInvalidDiscRegion: TNotifyEvent read FOnDVDErrorInvalidDiscRegion write FOnDVDErrorInvalidDiscRegion;
  795.  
  796.     { Player parental level is lower than the lowest parental level available in
  797.       the DVD content. Playback is stopped. }
  798.     property OnDVDErrorLowParentalLevel: TNotifyEvent read FOnDVDErrorLowParentalLevel write FOnDVDErrorLowParentalLevel;
  799.  
  800.     { Macrovision« distribution failed. Playback stopped. }
  801.     property OnDVDErrorMacrovisionFail: TNotifyEvent read FOnDVDErrorMacrovisionFail write FOnDVDErrorMacrovisionFail;
  802.  
  803.     { No discs can be played because the system region does not match the decoder region. }
  804.     property OnDVDErrorIncompatibleSystemAndDecoderRegions: TNotifyEvent read FOnDVDErrorIncompatibleSystemAndDecoderRegions write FOnDVDErrorIncompatibleSystemAndDecoderRegions;
  805.  
  806.     { The disc cannot be played because the disc is not authored to be played in
  807.       the decoder's region. }
  808.     property OnDVDErrorIncompatibleDiscAndDecoderRegions: TNotifyEvent read FOnDVDErrorIncompatibleDiscAndDecoderRegions  write FOnDVDErrorIncompatibleDiscAndDecoderRegions;
  809.  
  810.     { DVD-Video disc is authored incorrectly. Playback can continue, but unexpected
  811.       behavior might occur. }
  812.     property OnDVDWarningInvalidDVD1_0Disc: TNotifyEvent read FOnDVDWarningInvalidDVD1_0Disc write FOnDVDWarningInvalidDVD1_0Disc;
  813.  
  814.     { A decoder would not support the current format. Playback of a stream
  815.      (audio, video or subpicture) might not function. }
  816.     property OnDVDWarningFormatNotSupported : TNotifyEvent read FOnDVDWarningFormatNotSupported write FOnDVDWarningFormatNotSupported;
  817.  
  818.     { The internal DVD navigation command processor attempted to process an illegal command.}
  819.     property OnDVDWarningIllegalNavCommand  : TNotifyEvent read FOnDVDWarningIllegalNavCommand  write FOnDVDWarningIllegalNavCommand;
  820.  
  821.     { File Open failed. }
  822.     property OnDVDWarningOpen: TNotifyEvent read FOnDVDWarningOpen write FOnDVDWarningOpen;
  823.  
  824.     { File Seek failed. }
  825.     property OnDVDWarningSeek: TNotifyEvent read FOnDVDWarningSeek write FOnDVDWarningSeek;
  826.  
  827.     { File Read failed. }
  828.     property OnDVDWarningRead: TNotifyEvent read FOnDVDWarningRead write FOnDVDWarningRead;
  829.   end;
  830.  
  831.  
  832. // *****************************************************************************
  833. //   TVMROptions
  834. // *****************************************************************************
  835.  
  836.   {@exclude}
  837.   TVideoWindow = class;
  838.  
  839.   { See VRMOptions.<br>}
  840.   TVMRVideoMode = (
  841.     vmrWindowed,
  842.     vmrWindowless,
  843.     vmrRenderless
  844.   );
  845.  
  846.   { Video Mixer Renderer property editor. }
  847.   TVMROptions = class(TPersistent)
  848.   private
  849.     FOwner: TVideoWindow;
  850.     FStreams: cardinal;
  851.     FPreferences: TVMRPreferences;
  852.     FMode: TVMRVideoMode;
  853.     FKeepAspectRatio: boolean;
  854.     procedure SetStreams(Streams: cardinal);
  855.     procedure SetPreferences(Preferences: TVMRPreferences);
  856.     procedure SetMode(AMode: TVMRVideoMode);
  857.     procedure SetKeepAspectRatio(Keep: boolean);
  858.   public
  859.     { Constructor method. }
  860.     constructor Create(AOwner: TVideoWindow);
  861.   published
  862.     { Windowed or WindowLess}
  863.     property Mode: TVMRVideoMode read FMode write SetMode;
  864.     { Sets the number of streams to be mixed. }
  865.     property Streams: Cardinal read FStreams write SetStreams default 4;
  866.     { Sets various application preferences related to video rendering. }
  867.     property Preferences: TVMRPreferences read FPreferences write SetPreferences default [vpForceMixer];
  868.     { Keep Aspect Ration on the video window. }
  869.     property KeepAspectRatio: boolean read FKeepAspectRatio write SetKeepAspectRatio default True;
  870.   end;
  871.  
  872. // *****************************************************************************
  873. //   TVideoWindow
  874. // *****************************************************************************
  875.  
  876.   TAbstractAllocator = class(TInterfacedObject)
  877.     constructor Create(out hr: HResult; wnd: THandle; d3d: IDirect3D9 = nil; d3dd: IDirect3DDevice9 = nil); virtual; abstract;
  878.   end;
  879.   TAbstractAllocatorClass = class of TAbstractAllocator;
  880.  
  881.   { Manage a Video Renderer or a Video Mixer Renderer (VMR) Filter to display
  882.     a video in your application. }
  883.   TVideoWindow = class(TCustomControl, IFilter, IEvent)
  884.   private
  885.     FMode          : TVideoMode;
  886.     FVMROptions    : TVMROptions;
  887.     FBaseFilter    : IBaseFilter;
  888.     FVideoWindow   : IVideoWindow; // VMR Windowed & Normal
  889.     FWindowLess    : IVMRWindowlessControl9; // VMR Windowsless
  890.  
  891.     FFullScreen    : boolean;
  892.     FFilterGraph   : TFilterGraph;
  893.     FWindowStyle   : LongWord;
  894.     FWindowStyleEx : LongWord;
  895.     FTopMost       : boolean;
  896.     FIsFullScreen  : boolean;
  897.     FOnPaint       : TNotifyEvent;
  898.     FKeepAspectRatio: boolean;
  899.     FAllocatorClass: TAbstractAllocatorClass;
  900.     FCurrentAllocator: TAbstractAllocator;
  901.     FRenderLessUserID: Cardinal;
  902.     procedure SetVideoMode(AMode: TVideoMode);
  903.     procedure SetFilterGraph(AFilterGraph: TFilterGraph);
  904.     procedure SetFullScreen(Value: boolean);
  905.     procedure NotifyFilter(operation: TFilterOperation; Param: integer = 0);
  906.     procedure GraphEvent(Event, Param1, Param2: integer);
  907.     function GetName: string;
  908.     function GetVideoHandle: THandle;
  909.     procedure ControlEvent(Event: TControlEvent; Param: integer = 0);
  910.     procedure SetTopMost(TopMost: boolean);
  911.     function GetVisible: boolean;
  912.     procedure SetVisible(Vis: boolean);
  913.   protected
  914.     {@exclude}
  915.     procedure Loaded; override;
  916.     {@exclude}
  917.     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  918.     {@exclude}
  919.     procedure Resize; override;
  920.     {@exclude}
  921.     procedure ConstrainedResize(var MinWidth, MinHeight, MaxWidth, MaxHeight: Integer); override;
  922.     {@exclude}
  923.     function GetFilter: IBaseFilter;
  924.     {@exclude}
  925.     procedure WndProc(var Message: TMessage); override;
  926.     {@exclude}
  927.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  928.     {@exclude}
  929.     procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  930.     {@exclude}
  931.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  932.     {@exclude}
  933.     procedure Paint; override;
  934.   public
  935.     {@exclude}
  936.     function QueryInterface(const IID: TGUID; out Obj): HResult; override; stdcall;
  937.     { Constructor. }
  938.     constructor Create(AOwner: TComponent);override;
  939.     { Destructor. }
  940.     destructor Destroy; override;
  941.     { Check if the Video Mixer Renderer is available (Windows XP). }
  942.     class function CheckVMR: boolean;
  943.     { Retrieve the current bitmap, only in WindowLess VMR Mode. }
  944.     function VMRGetBitmap(Stream: TStream): boolean;
  945.     function CheckInputPinsConnected: boolean;
  946.     procedure SetAllocator(Allocator: TAbstractAllocatorClass; UserID: Cardinal);
  947.   published
  948.     { VMR/WindowsLess Mode only.}
  949.     property OnPaint: TNotifyEvent read FOnPaint write FOnPaint;
  950.     { The video Window stay on Top in FullScreen Mode. }
  951.     property FullScreenTopMost: boolean read FTopMost write SetTopMost default false;
  952.     { Video Mode, you can use Normal mode or VMR mode (VMR is only available on WindowsXP). }
  953.     property Mode: TVideoMode read FMode write SetVideoMode default vmNormal;
  954.     { The @link(TFilterGraph) component }
  955.     property FilterGraph: TFilterGraph read FFilterGraph write SetFilterGraph;
  956.     { Return the Handle where the video is displayed. }
  957.     property VideoHandle: THandle read GetVideoHandle;
  958.     { Video Mixer Renderer property editor. }
  959.     property VMROptions: TVMROptions read FVMROptions write FVMROptions;
  960.     { Set the full screen mode. }
  961.     property FullScreen: boolean read FFullScreen write SetFullScreen default false;
  962.     { Common properties & Events }
  963.                                    {@exclude}
  964.     property Color;                {@exclude}
  965.     property Visible: boolean read GetVisible write SetVisible default True; {@exclude}
  966.     property ShowHint;             {@exclude}
  967.     property Anchors;              {@exclude}
  968.     property Canvas;               {@exclude}
  969.     property PopupMenu;            {@exclude}
  970.     property Align;                {@exclude}
  971.     property TabStop default True; {@exclude}
  972.     property OnEnter;              {@exclude}
  973.     property OnExit;               {@exclude}
  974.     property OnKeyDown;            {@exclude}
  975.     property OnKeyPress;           {@exclude}
  976.     property OnKeyUp;              {@exclude}
  977.     property OnCanResize;          {@exclude}
  978.     property OnClick;              {@exclude}
  979.     property OnConstrainedResize;  {@exclude}
  980.     property OnDblClick;           {@exclude}
  981.     property OnMouseDown;          {@exclude}
  982.     property OnMouseMove;          {@exclude}
  983.     property OnMouseUp;            {@exclude}
  984.     property OnMouseWheel;         {@exclude}
  985.     property OnMouseWheelDown;     {@exclude}
  986.     property OnMouseWheelUp;       {@exclude}
  987.     property OnResize;
  988.   end;
  989.  
  990. //******************************************************************************
  991. //
  992. //  TFilterSampleGrabber declaration
  993. //  description: Sample Grabber Wrapper Filter
  994. //
  995. //******************************************************************************
  996.   {@exclude}
  997.   TSampleGrabber = class;
  998.  
  999.   { This class is designed make a snapshoot of Video or Audio Datas.
  1000.     WARNING: There is know problems with some DIVX movies, so use RGB32 Media Type
  1001.     instead of RBG24.}
  1002.   TSampleGrabber = class(TComponent, IFilter, ISampleGrabberCB)
  1003.   private
  1004.     FOnBuffer: TOnBuffer;
  1005.     FBaseFilter: IBaseFilter;
  1006.     FFilterGraph : TFilterGraph;
  1007.     FMediaType: TMediaType;
  1008.     BMPInfo : PBitmapInfo;
  1009.     FCriticalSection: TCriticalSection;
  1010.     function GetFilter: IBaseFilter;
  1011.     function GetName: string;
  1012.     procedure NotifyFilter(operation: TFilterOperation; Param: integer = 0);
  1013.     procedure SetFilterGraph(AFilterGraph: TFilterGraph);
  1014.     function  SampleCB(SampleTime: Double; pSample: IMediaSample): HResult; stdcall;
  1015.     function  BufferCB(SampleTime: Double; pBuffer: PByte; BufferLen: longint): HResult; stdcall;
  1016.   protected
  1017.     {@exclude}
  1018.     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  1019.   public
  1020.     { ISampleGrabber Interface to control the SampleGrabber Filter.
  1021.       The FilterGraph must be active.}
  1022.     SampleGrabber: ISampleGrabber;
  1023.     { The Input Pin.
  1024.       The FilterGraph must be active.}
  1025.     InPutPin  : IPin;
  1026.     { The Output Pin.
  1027.       The FilterGraph must be active.}
  1028.     OutPutPin : IPin;
  1029.     { Constructor method. }
  1030.     constructor Create(AOwner: TComponent); override;
  1031.     { Destructor method. }
  1032.     destructor Destroy; override;
  1033.     { Configure the filter to cature the specified MediaType.
  1034.       This mΘthod disconnect the Input pin if connected.
  1035.       The FilterGraph must be active. }
  1036.     procedure UpdateMediaType;
  1037.     {@exclude}
  1038.     function QueryInterface(const IID: TGUID; out Obj): HResult; override; stdcall;
  1039.     { Configure the MediaType according to the Source MediaType to be compatible with the BMP format.
  1040.       if Source = nil then this method use the default value to set the resolution: 1..32.
  1041.       The MediaType is auto configured to RGB24.}
  1042.     procedure SetBMPCompatible(Source: PAMMediaType; SetDefault: cardinal);
  1043.     { This method read the buffer received in the OnBuffer event and paint the bitmap.}
  1044.     function GetBitmap(Bitmap: TBitmap; Buffer: Pointer; BufferLen: Integer): boolean; overload;
  1045.     { This method read the current buffer from the Sample Grabber Filter and paint the bitmap.}
  1046.     function GetBitmap(Bitmap: TBitmap): boolean; overload;
  1047.     { This method check if the Sample Grabber Filter is correctly registered on the system. }
  1048.     class function CheckFilter: boolean;
  1049.   published
  1050.     { Receive the Buffer from the Sample Grabber Filter. }
  1051.     property OnBuffer: TOnBuffer read FOnBuffer write FOnBuffer;
  1052.     { The filter must connected to a TFilterGraph component.}
  1053.     property FilterGraph: TFilterGraph read FFilterGraph write SetFilterGraph;
  1054.     { The media type to capture. You can capture audio or video data. }
  1055.     property MediaType: TMediaType read FMediaType write FMediaType;
  1056.   end;
  1057.  
  1058. // *****************************************************************************
  1059. //  TFilter
  1060. // *****************************************************************************
  1061.  
  1062.   { This component is an easy way to add a specific filter to a filter graph.
  1063.     You can retrieve an interface using the <b>as</b> operator whith D6 :)}
  1064.   TFilter = class(TComponent, IFilter)
  1065.   private
  1066.     FFilterGraph : TFilterGraph;
  1067.     FBaseFilter: TBaseFilter;
  1068.     FFilter: IBaseFilter;
  1069.     function GetFilter: IBaseFilter;
  1070.     function GetName: string;
  1071.     procedure NotifyFilter(operation: TFilterOperation; Param: integer = 0);
  1072.     procedure SetFilterGraph(AFilterGraph: TFilterGraph);
  1073.   protected
  1074.     {@exclude}
  1075.     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  1076.   public
  1077.     { Constructor method. }
  1078.     constructor Create(AOwner: TComponent); override;
  1079.     { Destructor method. }
  1080.     destructor Destroy; override;
  1081.     { Retrieve a filter interface. }
  1082.     function QueryInterface(const IID: TGUID; out Obj): HResult; override; stdcall;
  1083.   published
  1084.     { This is the Filter Editor .}
  1085.     property BaseFilter: TBaseFilter read FBaseFilter write FBaseFilter;
  1086.     { The filter must be connected to a TFilterGraph component.}
  1087.     property FilterGraph: TFilterGraph read FFilterGraph write SetFilterGraph;
  1088.   end;
  1089.  
  1090. // *****************************************************************************
  1091. //  TASFWriter
  1092. // *****************************************************************************
  1093.  
  1094.   { This component is designed to create a ASF file or to stream over a network.}
  1095.   TASFWriter = class(TComponent, IFilter)
  1096.   private
  1097.     FFilterGraph : TFilterGraph;
  1098.     FFilter      : IBaseFilter;
  1099.     FPort        : Cardinal;
  1100.     FMaxUsers    : Cardinal;
  1101.     FProfile     : TWMPofiles8;
  1102.     FFileName    : WideString;
  1103.     FAutoIndex   : boolean;
  1104.     FMultiPass   : boolean;
  1105.     FDontCompress: boolean;
  1106.     function  GetProfile: TWMPofiles8;
  1107.     procedure SetProfile(profile: TWMPofiles8);
  1108.     function  GetFileName: String;
  1109.     procedure SetFileName(FileName: String);
  1110.     function  GetFilter: IBaseFilter;
  1111.     function  GetName: string;
  1112.     procedure NotifyFilter(operation: TFilterOperation; Param: integer = 0);
  1113.     procedure SetFilterGraph(AFilterGraph: TFilterGraph);
  1114.   protected
  1115.     {@exclude}
  1116.     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  1117.   public
  1118.     { Sink configuration. }
  1119.     WriterAdvanced2      : IWMWriterAdvanced2;
  1120.     { NetWork streaming configuration. }
  1121.     WriterNetworkSink    : IWMWriterNetworkSink;
  1122.     { The Audio Input Pin. }
  1123.     AudioInput           : IPin;
  1124.     { The Video Input Pin. }
  1125.     VideoInput           : IPin;
  1126.     { Audio Input configuration. }
  1127.     AudioStreamConfig    : IAMStreamConfig;
  1128.     { VideoInput configuration}
  1129.     VideoStreamConfig    : IAMStreamConfig;
  1130.     { Destructor method. }
  1131.     constructor Create(AOwner: TComponent); override;
  1132.     destructor Destroy; override;
  1133.     {@exclude}
  1134.     function QueryInterface(const IID: TGUID; out Obj): HResult; override; stdcall;
  1135.   published
  1136.     { The filter must be connected to a TFilterGraph component.}
  1137.     property FilterGraph: TFilterGraph read FFilterGraph write SetFilterGraph;
  1138.     { Windows media profile to use. }
  1139.     property Profile: TWMPofiles8 read GetProfile write SetProfile;
  1140.     { Destination file name to write the compressed file. }
  1141.     property FileName: String read GetFileName write SetFileName;
  1142.     { Port number to stream.}
  1143.     property Port: DWORD read FPort write FPort;
  1144.     { The max number of connections. }
  1145.     property MaxUsers: DWORD read FMaxUsers write FMaxUsers;
  1146.     property AutoIndex   : boolean read FAutoIndex write FAutoIndex default True;
  1147.     property MultiPass   : boolean read FMultiPass write FMultiPass default False;
  1148.     property DontCompress: boolean read FDontCompress write FDontCompress default False;
  1149.  
  1150.   end;
  1151.  
  1152. // *****************************************************************************
  1153. //  TDSTrackBar
  1154. // *****************************************************************************
  1155.   {@exclude}
  1156.   TTimerEvent = procedure(sender: TObject; CurrentPos, StopPos: Cardinal) of object ;
  1157.  
  1158.   { This control implement a seek bar for a media-player application.
  1159.     The seek bar is implemented as a TTrackbar control. }
  1160.   TDSTrackBar = class(TTrackBar, IEvent)
  1161.   private
  1162.     FFilterGraph: TFilterGraph;
  1163.     FMediaSeeking: IMediaSeeking;
  1164.     FWindowHandle: HWND;
  1165.     FInterval: Cardinal;
  1166.     FOnTimer: TTimerEvent;
  1167.     FEnabled: Boolean;
  1168.     FMouseDown: boolean;
  1169.     procedure UpdateTimer;
  1170.     procedure SetTimerEnabled(Value: Boolean);
  1171.     procedure SetInterval(Value: Cardinal);
  1172.     procedure SetOnTimer(Value: TTimerEvent);
  1173.     procedure SetFilterGraph(AFilterGraph: TFilterGraph);
  1174.     procedure GraphEvent(Event, Param1, Param2: integer);
  1175.     procedure ControlEvent(Event: TControlEvent; Param: integer = 0);
  1176.     procedure TimerWndProc(var Msg: TMessage);
  1177.     property TimerEnabled: Boolean read FEnabled write SetTimerEnabled;
  1178.   protected
  1179.     {@exclude}
  1180.     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  1181.     {@exclude}
  1182.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
  1183.       X, Y: Integer); override;
  1184.     {@exclude}
  1185.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
  1186.       X, Y: Integer); override;
  1187.     {@exclude}
  1188.     procedure Timer; dynamic;
  1189.   public
  1190.     { constructor method. }
  1191.     constructor Create(AOwner: TComponent); override;
  1192.     { destructor method. }
  1193.     destructor Destroy; override;
  1194.   published
  1195.     { Select the filtergraph to seek. }
  1196.     property FilterGraph: TFilterGraph read FFilterGraph Write SetFilterGraph;
  1197.     { Select the time interval in miliseconds. default = 1000 mls. }
  1198.     property TimerInterval: Cardinal read FInterval write SetInterval default 1000;
  1199.     { OnTimer event, you can retrieve the current and stop positions here. }
  1200.     property OnTimer: TTimerEvent read FOnTimer write SetOnTimer;
  1201.   end;
  1202.  
  1203.   { @exclude }
  1204.   TDSVideoWindowEx2 = class;
  1205.  
  1206. // *****************************************************************************
  1207. //  TColorControl
  1208. // *****************************************************************************
  1209.  
  1210.   { Set and Get ColorControls from DSVideoWindowEx's OverlayMixer.
  1211.     This is Hardware based so your graphic card has to support it.
  1212.     Check DSVideoWindowEx's Capabilities if your card support a given
  1213.     colorcontrol.}
  1214.   TColorControl = class(TPersistent)
  1215.   private
  1216.     FBrightness : Integer;
  1217.     FContrast   : Integer;
  1218.     FHue        : Integer;
  1219.     FSaturation : Integer;
  1220.     FSharpness  : Integer;
  1221.     FGamma      : Integer;
  1222.     FUtilColor  : Boolean;
  1223.     FDefault    : TDDColorControl;
  1224.   protected
  1225.     { Protected declarations }
  1226.     { @exclude }
  1227.     FOwner : TDSVideoWindowEx2;
  1228.     { @exclude }
  1229.     Procedure SetBrightness(Value : Integer);
  1230.     { @exclude }
  1231.     Procedure SetContrast(Value : Integer);
  1232.     { @exclude }
  1233.     procedure SetHue(Value : Integer);
  1234.     { @exclude }
  1235.     procedure SetSaturation(Value : Integer);
  1236.     { @exclude }
  1237.     procedure SetSharpness(Value : Integer);
  1238.     { @exclude }
  1239.     procedure SetGamma(Value : Integer);
  1240.     { @exclude }
  1241.     procedure SetUtilColor(Value : Boolean);
  1242.  
  1243.     { @exclude }
  1244.     function GetBrightness : Integer;
  1245.     { @exclude }
  1246.     function GetContrast : Integer;
  1247.     { @exclude }
  1248.     function GetHue : Integer;
  1249.     { @exclude }
  1250.     function GetSaturation : Integer;
  1251.     { @exclude }
  1252.     function GetSharpness : Integer;
  1253.     { @exclude }
  1254.     function GetGamma : Integer;
  1255.     { @exclude }
  1256.     function GetUtilColor : Boolean;
  1257.     { @exclude }
  1258.     Procedure ReadDefault;
  1259.     { @exclude }
  1260.     procedure UpdateColorControls;
  1261.     { @exclude }
  1262.     procedure GetColorControls;
  1263.   public
  1264.     { Public declarations }
  1265.     { @exclude }
  1266.     constructor Create(AOwner: TDSVideoWindowEx2);  virtual;
  1267.     { Restore the colorcontrols to there (Default) values.
  1268.       Default is the value the colorcontrol hat, just after we initilized the overlay Mixer. }
  1269.     procedure RestoreDefault;
  1270.   Published
  1271.     { The Brightness property defines the luminance intensity, in IRE units, multiplied by 100.
  1272.       The possible range is from 0 to 10,000 with a default of 750.}
  1273.     property Brightness : Integer read GetBrightness write SetBrightness;
  1274.  
  1275.     { The Contrast property defines the relative difference between higher and lower luminance values, in IRE units, multiplied by 100.
  1276.       The possible range is from 0 to 20,000 with a default value of 10,000. }
  1277.     property Contrast : Integer read GetContrast write SetContrast;
  1278.  
  1279.     { The Hue property defines the phase relationship, in degrees, of the chrominance components.
  1280.       The possible range is from -180 to 180, with a default of 0.}
  1281.     property Hue : Integer read GetHue write SetHue;
  1282.  
  1283.     { The Saturation property defines the color intensity, in IRE units, multiplied by 100.
  1284.       The possible range is 0 to 20,000, with a default value of 10,000.}
  1285.     property Saturation : Integer read GetSaturation write SetSaturation;
  1286.  
  1287.     { The Sharpness property defines the sharpness, in arbitrary units, of an image.
  1288.       The possible range is 0 to 10, with a default value of 5.}
  1289.     property Sharpness : Integer read GetSharpness write SetSharpness;
  1290.  
  1291.     { The Gamma property defines the amount, in gamma units, of gamma correction applied to the luminance values.
  1292.       The possible range is from 1 to 500, with a default of 1.}
  1293.     property Gamma : Integer read GetGamma write SetGamma;
  1294.  
  1295.     { The ColorEnable property defines whether color is utilized or not.
  1296.       Color is used if this property is 1. Color is not used if this property is 0. The default value is 1.}
  1297.     property ColorEnable : Boolean read GetUtilColor write SetUtilColor;
  1298.   end;
  1299.  
  1300. // *****************************************************************************
  1301. //  TDSVideoWindowEx2Caps
  1302. // *****************************************************************************
  1303.  
  1304.   { Check capability of DSVideoWindowEx. }
  1305.   TDSVideoWindowEx2Caps = class(TPersistent)
  1306.   protected
  1307.     { Protected declarations }
  1308.     Owner : TDSVideoWindowEx2;
  1309.     function GetCanOverlay : Boolean;
  1310.     function GetCanControlBrigtness : Boolean;
  1311.     function GetCanControlContrast : Boolean;
  1312.     function GetCanControlHue : Boolean;
  1313.     function GetCanControlSaturation : Boolean;
  1314.     function GetCanControlSharpness : Boolean;
  1315.     function GetCanControlGamma : Boolean;
  1316.     function GetCanControlUtilizedColor : Boolean;
  1317.   public
  1318.     { Public declarations }
  1319.     { @exclude }
  1320.     constructor Create(AOwner: TDSVideoWindowEx2);  virtual;
  1321.   published
  1322.     { if CanOverlayGraphics return true, you draw on DSVideoWindowEx's canvas and the
  1323.       graphic will bee ontop of the Video.}
  1324.     Property CanOverlayGraphic : Boolean read GetCanOverlay;
  1325.  
  1326.     { Repport if you can control Brightness on the video overlay }
  1327.     Property CanControlBrigtness : Boolean read GetCanControlBrigtness;
  1328.     { Repport if you can control Contrast on the video overlay }
  1329.     Property CanControlContrast : Boolean read GetCanControlContrast;
  1330.     { Repport if you can control Hue on the video overlay }
  1331.     Property CanControlHue : Boolean read GetCanControlHue;
  1332.     { Repport if you can control Saturation on the video overlay }
  1333.     Property CanControlSaturation : Boolean read GetCanControlSaturation;
  1334.     { Repport if you can control Sharpness on the video overlay }
  1335.     Property CanControlSharpness : Boolean read GetCanControlSharpness;
  1336.     { Repport if you can control Gamma on the video overlay }
  1337.     Property CanControlGamma : Boolean read GetCanControlGamma;
  1338.     { Repport if you can control ColorEnabled on the video overlay }
  1339.     Property CanControlColorEnabled : Boolean read GetCanControlUtilizedColor;
  1340.   end;
  1341.  
  1342. // *****************************************************************************
  1343. //  TOverlayCallback
  1344. // *****************************************************************************
  1345.  
  1346.   { @exclude }
  1347.   TOverlayCallback = class(TInterfacedObject, IDDrawExclModeVideoCallBack)
  1348.     AOwner : TObject;
  1349.     constructor Create(Owner : TObject); virtual;
  1350.     function OnUpdateOverlay(bBefore: BOOL; dwFlags: DWORD; bOldVisible: BOOL;
  1351.              var prcOldSrc, prcOldDest: TRECT; bNewVisible: BOOL; var prcNewSrc, prcNewDest: TRECT): HRESULT; stdcall;
  1352.     function OnUpdateColorKey(var pKey: TCOLORKEY; dwColor: DWORD): HRESULT; stdcall;
  1353.     function OnUpdateSize(dwWidth, dwHeight, dwARWidth, dwARHeight: DWORD): HRESULT; stdcall;
  1354.   end;
  1355.  
  1356. // *****************************************************************************
  1357. //  TDSVideoWindowEx2
  1358. // *****************************************************************************
  1359.  
  1360.   { @exclude }
  1361.   TRatioModes  = (rmStretched, rmLetterBox, rmCrop);
  1362.  
  1363.   { @exclude }
  1364.   TOverlayVisibleEvent = procedure (Sender: TObject; Visible : Boolean) of object;
  1365.  
  1366.   { @exclude }
  1367.   TCursorVisibleEvent = procedure (Sender: TObject; Visible : Boolean) of object;
  1368.  
  1369.   { A alternative to the regular Video Renderer (TVideoWindow), that give a easy way to overlay graphics
  1370.     onto your video in your application. }
  1371.   TDSVideoWindowEx2 = class(TCustomControl, IFilter, IEvent)
  1372.   private
  1373.     FVideoWindow       : IVideoWindow;
  1374.     FFilterGraph       : TFilterGraph;
  1375.     FBaseFilter        : IBaseFilter;
  1376.     FOverlayMixer      : IBaseFilter;
  1377.     FVideoRenderer     : IBaseFilter;
  1378.     FDDXM              : IDDrawExclModeVideo;
  1379.     FFullScreen        : Boolean;
  1380.     FTopMost           : Boolean;
  1381.     FColorKey          : TColor;
  1382.     FWindowStyle       : LongWord;
  1383.     FWindowStyleEx     : LongWord;
  1384.     FVideoRect         : TRect;
  1385.     FOnPaint           : TNotifyEvent;
  1386.     FOnColorKey        : TNotifyEvent;
  1387.     FOnCursorVisible   : TCursorVisibleEvent;
  1388.     FOnOverlay         : TOverlayVisibleEvent;
  1389.     FColorControl      : TColorControl;
  1390.     FCaps              : TDSVideoWindowEx2Caps;
  1391.     FZoom              : Integer;
  1392.     FAspectMode        : TRatioModes;
  1393.     FNoScreenSaver     : Boolean;
  1394.     FIdleCursor        : Integer;
  1395.     FMonitor           : TMonitor;
  1396.     FFullscreenControl : TForm;
  1397.     GraphWasUpdatet    : Boolean;
  1398.     FOldParent         : TWinControl;
  1399.     OverlayCallback    : TOverlayCallback;
  1400.     GraphBuildOK       : Boolean;
  1401.     FVideoWindowHandle : HWND;
  1402.     LMousePos          : TPoint;
  1403.     LCursorMov         : DWord;
  1404.     RememberCursor     : TCursor;
  1405.     IsHidden           : Bool;
  1406.     FOverlayVisible    : Boolean;
  1407.     OldDesktopColor    : Longint;
  1408.     OldDesktopPic      : String;
  1409.     FDesktopPlay       : Boolean;
  1410.     procedure NotifyFilter(operation: TFilterOperation; Param: integer = 0);
  1411.     procedure GraphEvent(Event, Param1, Param2: integer);
  1412.     function GetName: string;
  1413.     procedure ControlEvent(Event: TControlEvent; Param: integer = 0);
  1414.     procedure SetFilterGraph(AFilterGraph: TFilterGraph);
  1415.     procedure SetTopMost(TopMost: boolean);
  1416.     procedure SetZoom(Value : Integer);
  1417.     function UpdateGraph : HResult;
  1418.     function GetVideoInfo : HResult;
  1419.     procedure SetAspectMode(Value : TRatioModes);
  1420.     procedure FullScreenCloseQuery(Sender: TObject; var CanClose: Boolean);
  1421.     procedure SetVideoZOrder;
  1422.   protected
  1423.     {@exclude}
  1424.     function GetFilter: IBaseFilter;
  1425.     {@exclude}
  1426.     procedure resize; override;
  1427.     {@exclude}
  1428.     procedure Loaded; override;
  1429.     {@exclude}
  1430.     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  1431.     {@exclude}
  1432.     procedure WndProc(var Message: TMessage); override;
  1433.     {@exclude}
  1434.     procedure Paint; override;
  1435.     {@exclude}
  1436.     procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  1437.     {@exclude}
  1438.     procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
  1439.     {@exclude}
  1440.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
  1441.     {@exclude}
  1442.     procedure MyIdleHandler(Sender: TObject; var Done: Boolean);
  1443.     {@exclude}
  1444.     procedure RefreshVideoWindow;
  1445.   public
  1446.     { constructor method. }
  1447.     constructor Create(AOwner: TComponent); override;
  1448.     { destructor method. }
  1449.     destructor Destroy; override;
  1450.  
  1451.     {@exclude}
  1452.     function QueryInterface(const IID: TGUID; out Obj): HResult; override; stdcall;
  1453.  
  1454.     { Clear the graphic ontop of DSVideoWindowEx. }
  1455.     procedure ClearBack;
  1456.  
  1457.     { Use your Desktop as the Video renderer.
  1458.       The video will display as a "wallpaper" on your Desktop }
  1459.     procedure StartDesktopPlayback; overload;
  1460.  
  1461.     { Use your Desktop as the Video renderer.
  1462.       The video will display as a "wallpaper" on your Desktop on the
  1463.       specifyed monitor}
  1464.     procedure StartDesktopPlayBack(OnMonitor : TMonitor); overload;
  1465.  
  1466.     { Return to normal window playback from Fullscreen or Desktop mode. }
  1467.     procedure NormalPlayback;
  1468.  
  1469.     { Start playback in fullscreen }
  1470.     procedure StartFullScreen; overload;
  1471.  
  1472.     { Start playback in fullscreen on specifyed Monitor}
  1473.     procedure StartFullScreen(OnMonitor : TMonitor); overload;
  1474.  
  1475.     { repporting if you are currently playing in fullscreen. }
  1476.     property FullScreen: boolean read FFullScreen;
  1477.  
  1478.     { repporting if you are currently playing on the Desktop. }
  1479.     property DesktopPlayback : Boolean Read FDesktopPlay;
  1480.     { @inherited }
  1481.     property Canvas;
  1482.  
  1483.     { The Colorkey is the color that the Overlay Mixer Filter used by DSVideoWindowEx sees
  1484.       as transparent, when you draw ontop of the movie always set the canvasÆs brush
  1485.       color to this color or set the style to bsclear.
  1486.       Note: The colors returned through this method vary depending on the current display mode.
  1487.       if the colors are 8-bit palettized, they will be bright system colors (such as magenta).
  1488.       if the display is in a true-color mode, they will be shades of black. }
  1489.     property ColorKey : TColor read FColorKey;
  1490.  
  1491.     { @link(TDSVideoWindowEx2Caps) }
  1492.     property Capabilities : TDSVideoWindowEx2Caps read FCaps;
  1493.  
  1494.     { Check this property to see if the overlay is visible when you draw on DSVideoWindowEx's
  1495.       canvas, if it is visible you should set your brush color to the same as the VideoColor and
  1496.       if not set your brush to the same color as DSVideoWindowEx color. }
  1497.     property OverlayVisible : Boolean read FOverlayVisible;
  1498.   published
  1499.     { The AspectRatio property sets the aspect ratio correction mode for window resizing.
  1500.         rmSTRETCHED : No aspect ratio correction.
  1501.         rmLETTERBOX : Put the video in letterbox format. Paint background color in the
  1502.                       excess region  so the video is not distorted.
  1503.         rmCROP      : Crop the video to the correct aspect ratio. }
  1504.     property AspectRatio : TRatioModes read FAspectMode write SetAspectMode;
  1505.  
  1506.     { Set the amounts of milliseconds befor the cursor is hidden, if it is not moved.
  1507.       Setting the value to 0 will disable this feature. }
  1508.     property AutoHideCursor : Integer read FIdleCursor write FIdleCursor;
  1509.  
  1510.     { Specify a Zoom factor from 0 to 99 procent. }
  1511.     property DigitalZoom : Integer read FZoom write SetZoom;
  1512.  
  1513.     { The @link(TFilterGraph) component }
  1514.     property FilterGraph: TFilterGraph read FFilterGraph write SetFilterGraph;
  1515.  
  1516.     { Select if the VideoWindow it topmost or not. }
  1517.     property FullScreenTopMost: boolean read FTopMost write SetTopMost default false;
  1518.  
  1519.     { Event to tell the main application that the Colorkey has changed.
  1520.       Note: if you have controls placed ontop of your VideoWindow that need to act as
  1521.             transparent, set there color to the same as the Colorkey.}
  1522.     property OnColorKeyChanged: TNotifyEvent read FOnColorKey write FOnColorKey;
  1523.  
  1524.     { @link(TColorControl) }
  1525.     property ColorControl : TColorControl read FColorControl write FColorControl;
  1526.  
  1527.     { Setting this to true will prevent the screen to go into screensaver or powerdown. }
  1528.     property NoScreenSaver : Boolean read FNoScreenSaver write FNoScreenSaver;
  1529.  
  1530.     { This event accure when the Visible state of the overlay changes
  1531.       Note: Most used to hide the video in the player window when going to
  1532.             DesktopPlayback. }
  1533.     property OnOverlayVisible : TOverlayVisibleEvent read FOnOverlay write FOnOverlay;
  1534.  
  1535.     property OnPaint : TNotifyevent read FOnPaint Write FOnPaint;
  1536.  
  1537.     { This event accure when the cursor change from showing to hiding or from hiding to showing. }
  1538.     property OnCursorShowHide : TCursorVisibleEvent read FOnCursorVisible write FOnCursorVisible;
  1539.  
  1540.     property Color;                {@exclude}
  1541.     property Visible;              {@exclude}
  1542.     property ShowHint;             {@exclude}
  1543.     property Anchors;              {@exclude}
  1544.     property PopupMenu;            {@exclude}
  1545.     property Align;                {@exclude}
  1546.     property TabStop default True; {@exclude}
  1547.     property OnEnter;              {@exclude}
  1548.     property OnExit;               {@exclude}
  1549.     property OnKeyDown;            {@exclude}
  1550.     property OnKeyPress;           {@exclude}
  1551.     property OnKeyUp;              {@exclude}
  1552.     property OnCanResize;          {@exclude}
  1553.     property OnClick;              {@exclude}
  1554.     property OnConstrainedResize;  {@exclude}
  1555.     property OnDblClick;           {@exclude}
  1556.     property OnMouseDown;          {@exclude}
  1557.     property OnMouseMove;          {@exclude}
  1558.     property OnMouseUp;            {@exclude}
  1559.     property OnMouseWheel;         {@exclude}
  1560.     property OnMouseWheelDown;     {@exclude}
  1561.     property OnMouseWheelUp;       {@exclude}
  1562.     property OnResize;
  1563.   end;
  1564.  
  1565. ////////////////////////////////////////////////////////////////////////////////
  1566. //
  1567. // TVMRBitmap Class
  1568. //
  1569. ////////////////////////////////////////////////////////////////////////////////
  1570. type
  1571.  
  1572.   { vmrbDisable: Disable the alpha bitmap.
  1573.     vmrbSrcColorKey: Enable ColorKey.
  1574.     vmrbSrcRect: Indicates that the Dest property is valid and specifies
  1575.     a sub-rectangle of the original image to be blended. }
  1576.  
  1577.   TVMRBitmapOption = (
  1578.     vmrbDisable,
  1579.     vmrbSrcColorKey,
  1580.     vmrbSrcRect
  1581.   );
  1582.   TVMRBitmapOptions = set of TVMRBitmapOption;
  1583.  
  1584.   TVMRBitmap = class
  1585.   private
  1586.     FVideoWindow: TVideoWindow;
  1587.     FCanvas: TCanvas;
  1588.     FVMRALPHABITMAP: TVMR9ALPHABITMAP;
  1589.     FOptions: TVMRBitmapOptions;
  1590.     FBMPOld: HBITMAP;
  1591.     procedure SetOptions(Options: TVMRBitmapOptions);
  1592.     procedure ResetBitmap;
  1593.     procedure SetAlpha(const Value: Single);
  1594.     procedure SetColorKey(const Value: COLORREF);
  1595.     procedure SetDest(const Value: TVMR9NormalizedRect);
  1596.     procedure SetDestBottom(const Value: Single);
  1597.     procedure SetDestLeft(const Value: Single);
  1598.     procedure SetDestRight(const Value: Single);
  1599.     procedure SetDestTop(const Value: Single);
  1600.     procedure SetSource(const Value: TRect);
  1601.     function GetAlpha: Single;
  1602.     function GetColorKey: COLORREF;
  1603.     function GetDest: TVMR9NormalizedRect;
  1604.     function GetDestBottom: Single;
  1605.     function GetDestLeft: Single;
  1606.     function GetDestRight: Single;
  1607.     function GetDestTop: Single;
  1608.     function GetSource: TRect;
  1609.   public
  1610.     // Contructor, set the video Window where the bitmat must be paint.
  1611.     constructor Create(VideoWindow: TVideoWindow);
  1612.     // Cleanup
  1613.     destructor Destroy; override;
  1614.     // Load a Bitmap from a TBitmap class.
  1615.     procedure LoadBitmap(Bitmap: TBitmap);
  1616.     // Initialize with an empty bitmap.
  1617.     procedure LoadEmptyBitmap(Width, Height: Integer; PixelFormat: TPixelFormat; Color: TColor);
  1618.     // Draw the bitmap to the Video Window.
  1619.     procedure Draw;
  1620.     // Draw the bitmap on a particular position.
  1621.     procedure DrawTo(Left, Top, Right, Bottom, Alpha: Single; doUpdate: boolean = false);
  1622.     // update the video window with the current bitmap
  1623.     procedure Update;
  1624.     // Uses this property to draw on the internal bitmap.
  1625.     property Canvas: TCanvas read FCanvas write FCanvas;
  1626.     // Change Alpha Blending
  1627.     property Alpha: Single read GetAlpha write SetAlpha;
  1628.     // set the source rectangle
  1629.     property Source: TRect read GetSource write SetSource;
  1630.     // Destination Left
  1631.     property DestLeft   : Single read GetDestLeft write SetDestLeft;
  1632.     // Destination Top
  1633.     property DestTop    : Single read GetDestTop write SetDestTop;
  1634.     // Destination Right
  1635.     property DestRight  : Single read GetDestRight write SetDestRight;
  1636.     // Destination Bottom
  1637.     property DestBottom : Single read GetDestBottom write SetDestBottom;
  1638.     // Destination
  1639.     property Dest: TVMR9NormalizedRect read GetDest write SetDest;
  1640.     // Set the color key for transparency.
  1641.     property ColorKey: COLORREF read GetColorKey write SetColorKey;
  1642.     // VMR Bitmap Options.
  1643.     property Options: TVMRBitmapOptions read FOptions write SetOptions;
  1644.   end;
  1645.  
  1646. implementation
  1647.  
  1648. uses ComObj;
  1649.  
  1650. // *****************************************************************************
  1651. //  TFilterGraph
  1652. // *****************************************************************************
  1653.  
  1654.  
  1655.   constructor TFilterGraph.Create(AOwner: TComponent);
  1656.   begin
  1657.     inherited Create(AOwner);
  1658.     FHandle := AllocateHWnd(WndProc);
  1659.   end;
  1660.  
  1661.   destructor TFilterGraph.Destroy;
  1662.   begin
  1663.     SetActive(False);
  1664.     DeallocateHWnd(FHandle);
  1665.     inherited Destroy;
  1666.   end;
  1667.  
  1668.   procedure TFilterGraph.SetGraphMode(Mode: TGraphMode);
  1669.   var WasActive: boolean;
  1670.   begin
  1671.     if FMode = Mode then exit;
  1672.     WasActive := Active;
  1673.     Active := False;
  1674.     FMode := Mode;
  1675.     Active := WasActive;
  1676.   end;
  1677.  
  1678.   procedure TFilterGraph.SetActive(Activate: boolean);
  1679.   begin
  1680.     if Activate = FActive then exit;
  1681.     case Activate of
  1682.       true :
  1683.         begin
  1684.           case FMode of
  1685.             gmNormal : CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC_SERVER, IID_IFilterGraph2, FFilterGraph);
  1686.             gmCapture: begin
  1687.                          CoCreateInstance(CLSID_CaptureGraphBuilder2, nil, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, FCaptureGraph);
  1688.                          CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC_SERVER, IID_IFilterGraph2, FFilterGraph);
  1689.                          FCaptureGraph.SetFiltergraph(IGraphBuilder(FFilterGraph));
  1690.                        end;
  1691.             gmDVD    : begin
  1692.                          CoCreateInstance(CLSID_DvdGraphBuilder, nil, CLSCTX_INPROC_SERVER, IID_IDvdGraphBuilder, FDvdGraph);
  1693.                          FDvdGraph.GetFiltergraph(IGraphBuilder(FFilterGraph));
  1694.                        end;
  1695.           end;
  1696.           FActive := true;
  1697.           // Events
  1698.           if Succeeded(QueryInterface(IMediaEventEx, FMediaEventEx)) then
  1699.           begin
  1700.             FMediaEventEx.SetNotifyFlags(0); // enable events notification
  1701.             FMediaEventEx.SetNotifyWindow(FHandle,WM_GRAPHNOTIFY,ULONG(FMediaEventEx));
  1702.           end;
  1703.           // Remote Object Table
  1704.           GraphEdit := FGraphEdit; // Add the Filter Graph to the ROT if needed.
  1705.           // Log File
  1706.           SetLogFile(FLogFileName);
  1707.           // Load Filters
  1708.           AddOwnFilters;
  1709.           // Notify Controlers
  1710.           if assigned(FOnActivate) then FOnActivate(self);
  1711.           ControlEvents(ceActive, 1);
  1712.         end;
  1713.       false:
  1714.         begin
  1715.           ControlEvents(ceActive, 0);
  1716.           ClearOwnFilters;
  1717.           if FMediaEventEx <> nil then
  1718.           begin
  1719.             FMediaEventEx.SetNotifyFlags(AM_MEDIAEVENT_NONOTIFY); // disable events notification
  1720.             FMediaEventEx := nil;
  1721.           end;
  1722.           if FGraphEditID <> 0 then
  1723.           begin
  1724.             RemoveGraphFromRot(FGraphEditID);
  1725.             FGraphEditID := 0;
  1726.           end;
  1727.           FFilterGraph.SetLogFile(0);
  1728.           if Assigned(FLogFile) then FreeAndNil(FLogFile);
  1729.  
  1730.           FFilterGraph  := nil;
  1731.           FCaptureGraph := nil;
  1732.           FDVDGraph     := nil;
  1733.           FActive := false;
  1734.         end;
  1735.     end;
  1736.   end;
  1737.  
  1738.   procedure TFilterGraph.Loaded;
  1739.   begin
  1740.     if AutoCreate and (not (csDesigning in ComponentState)) then SetActive(True);
  1741.     inherited Loaded;
  1742.   end;
  1743.  
  1744.   procedure TFilterGraph.WndProc(var Msg: TMessage);
  1745.   begin
  1746.   with Msg do
  1747.     if Msg = WM_GRAPHNOTIFY then
  1748.       try
  1749.         HandleEvents;
  1750.       except
  1751.         Application.HandleException(Self);
  1752.       end
  1753.     else
  1754.       Result := DefWindowProc(FHandle, Msg, wParam, lParam);
  1755.   end;
  1756.  
  1757.   procedure TFilterGraph.HandleEvents;
  1758.   var hr: HRESULT;
  1759.       Event, Param1, Param2: Integer;
  1760.   begin
  1761.     if assigned(FMediaEventEx) then
  1762.     begin
  1763.       hr := FMediaEventEx.GetEvent(Event, Param1, Param2, 0);
  1764.       while (hr = S_OK) do
  1765.       begin
  1766.         DoEvent(Event, Param1, Param2);
  1767.         FMediaEventEx.FreeEventParams(Event, Param1, Param2);
  1768.         hr := FMediaEventEx.GetEvent(Event, Param1, Param2, 0);
  1769.       end;
  1770.     end;
  1771.   end;
  1772.  
  1773.   procedure TFilterGraph.DoEvent(Event, Param1, Param2: Integer);
  1774.   type
  1775.     TVideoSize = record
  1776.       Width : WORD;
  1777.       Height: WORD;
  1778.     end;
  1779.   var
  1780.     lcid    : cardinal;
  1781.     achLang : array[0..MAX_PATH] of Char;
  1782.     tc      : TDVDTimeCode;
  1783.     frate   : integer;
  1784.     hmsftc  : TDVDHMSFTimeCode;
  1785.     DVDInfo2: IDVDInfo2;
  1786.   begin
  1787.     GraphEvents(Event, Param1, Param2);
  1788.     if assigned(FOnDSEvent) then FOnDSEvent(self, Event, Param1, Param2);
  1789.     case Event of
  1790.       EC_BUFFERING_DATA            : if assigned(FOnGraphBufferingData)           then FOnGraphBufferingData(self,(Param1 = 1));
  1791.       EC_CLOCK_CHANGED             : if assigned(FOnGraphClockChanged)            then FOnGraphClockChanged(self);
  1792.       EC_COMPLETE                  : if assigned(FOnGraphComplete)                then FOnGraphComplete(self, Param1, IBaseFilter(Param2));
  1793.       EC_DEVICE_LOST               : if assigned(FOnGraphDeviceLost)              then FOnGraphDeviceLost(self,IUnKnown(Param1),(Param2 = 1));
  1794.       EC_END_OF_SEGMENT            : if assigned(FOnGraphEndOfSegment)            then FOnGraphEndOfSegment(self, PReferenceTime(Param1)^, Param2);
  1795.       EC_ERROR_STILLPLAYING        : if assigned(FOnGraphErrorStillPlaying)       then FOnGraphErrorStillPlaying(self, Param1);
  1796.       EC_ERRORABORT                : if assigned(FOnGraphErrorAbort)              then FOnGraphErrorAbort(self, Param1);
  1797.       EC_FULLSCREEN_LOST           : if assigned(FOnGraphFullscreenLost)          then FOnGraphFullscreenLost(self, IBaseFilter(Param2));
  1798.       EC_GRAPH_CHANGED             : if assigned(FOnGraphChanged)                 then FOnGraphChanged(self);
  1799.       EC_OLE_EVENT                 : if assigned(FOnGraphOleEvent)                then FOnGraphOleEvent(self, WideString(Param1), WideString(Param2));
  1800.       EC_OPENING_FILE              : if assigned(FOnGraphOpeningFile)             then FOnGraphOpeningFile(self, (Param1 = 1));
  1801.       EC_PALETTE_CHANGED           : if assigned(FOnGraphPaletteChanged)          then FOnGraphPaletteChanged(self);
  1802.       EC_PAUSED                    : if assigned(FOnGraphPaused)                  then FOnGraphPaused(self, Param1);
  1803.       EC_QUALITY_CHANGE            : if assigned(FOnGraphQualityChange)           then FOnGraphQualityChange(self);
  1804.       EC_SNDDEV_IN_ERROR           : if assigned(FOnGraphSNDDevInError)           then FOnGraphSNDDevInError(self, TSndDevErr(Param1), Param2);
  1805.       EC_SNDDEV_OUT_ERROR          : if assigned(FOnGraphSNDDevOutError)          then FOnGraphSNDDevOutError(self, TSndDevErr(Param1), Param2);
  1806.       EC_STEP_COMPLETE             : if assigned(FOnGraphStepComplete)            then FOnGraphStepComplete(self);
  1807.       EC_STREAM_CONTROL_STARTED    : if assigned(FOnGraphStreamControlStarted)    then FOnGraphStreamControlStarted(self, IPin(Param1), Param2);
  1808.       EC_STREAM_CONTROL_STOPPED    : if assigned(FOnGraphStreamControlStopped)    then FOnGraphStreamControlStopped(self, IPin(Param1), Param2);
  1809.       EC_STREAM_ERROR_STILLPLAYING : if assigned(FOnGraphStreamErrorStillPlaying) then FOnGraphStreamErrorStillPlaying(self, Param1, Param2);
  1810.       EC_STREAM_ERROR_STOPPED      : if assigned(FOnGraphStreamErrorStopped)      then FOnGraphStreamErrorStopped(self, Param1, Param2);
  1811.       EC_USERABORT                 : if assigned(FOnGraphUserAbort)               then FOnGraphUserAbort(self);
  1812.       EC_VIDEO_SIZE_CHANGED        : if assigned(FOnGraphVideoSizeChanged)        then FOnGraphVideoSizeChanged(self, TVideoSize(Param1).Width, TVideoSize(Param1).Height);
  1813.       EC_TIMECODE_AVAILABLE        : if assigned(FOnGraphTimeCodeAvailable)       then FOnGraphTimeCodeAvailable(self,IBaseFilter(Param1), Param2);
  1814.       EC_EXTDEVICE_MODE_CHANGE     : if assigned(FOnGraphEXTDeviceModeChange)     then FOnGraphEXTDeviceModeChange(self, Param1, Param2);
  1815.       EC_CLOCK_UNSET               : if assigned(FOnGraphClockUnset)              then FOnGraphClockUnset(self);
  1816.       EC_VMR_RENDERDEVICE_SET      : if assigned(FOnGraphVMRRenderDevice)         then FOnGraphVMRRenderDevice(self, TVMRRenderDevice(Param1)) ;
  1817.  
  1818.       EC_DVD_ANGLE_CHANGE            : if Assigned(FOnDVDAngleChange) then FOnDVDAngleChange(self,Param1,Param2);
  1819.       EC_DVD_AUDIO_STREAM_CHANGE     :
  1820.         begin
  1821.           if Assigned(FOnDVDAudioStreamChange) then
  1822.           if Succeeded(QueryInterFace(IDVDInfo2,DVDInfo2)) then
  1823.           begin
  1824.             CheckDSError(DvdInfo2.GetAudioLanguage(Param1, lcid));
  1825.             GetLocaleInfo(lcid, LOCALE_SENGLANGUAGE, achLang, MAX_PATH);
  1826.             FOnDVDAudioStreamChange(self, Param1, lcid, string(achLang));
  1827.             DVDInfo2 := nil;
  1828.           end;
  1829.         end;
  1830.       EC_DVD_BUTTON_CHANGE           : if Assigned(FOnDVDButtonChange) then FOnDVDButtonChange(self, Param1, Param2);
  1831.       EC_DVD_CHAPTER_AUTOSTOP        : if Assigned(FOnDVDChapterAutoStop) then FOnDVDChapterAutoStop(self);
  1832.       EC_DVD_CHAPTER_START           : if Assigned(FOnDVDChapterStart) then FOnDVDChapterStart(self, Param1);
  1833.       EC_DVD_CURRENT_TIME            :
  1834.         begin
  1835.           if Assigned(FOnDVDCurrentTime) then
  1836.           begin
  1837.             tc := IntToTimeCode(Param1);
  1838.             case tc.FrameRateCode of
  1839.               1 : frate := 25;
  1840.               3 : frate := 30;
  1841.             else
  1842.               frate := 0;
  1843.             end;
  1844.             FOnDVDCurrentTime(self,tc.Hours1+tc.Hours10*10,tc.Minutes1+tc.Minutes10*10,tc.Seconds1+tc.Seconds10*10,tc.Frames1+tc.Frames10*10,frate);
  1845.           end;
  1846.         end;
  1847.       EC_DVD_DOMAIN_CHANGE           :
  1848.         begin
  1849.           case Param1 of
  1850.             1 : if Assigned(FOnDVDDomainFirstPlay) then FOnDVDDomainFirstPlay(self);
  1851.             2 : if Assigned(FOnDVDDomainVideoManagerMenu) then FOnDVDDomainVideoManagerMenu(self);
  1852.             3 : if Assigned(FOnDVDDomainVideoTitleSetMenu) then FOnDVDDomainVideoTitleSetMenu(self);
  1853.             4 : if Assigned(FOnDVDDomainTitle) then FOnDVDDomainTitle(self);
  1854.             5 : if Assigned(FOnDVDDomainStop) then FOnDVDDomainStop(self);
  1855.           end;
  1856.         end;
  1857.       EC_DVD_ERROR                   :
  1858.         begin
  1859.           case Param1 of
  1860.             1 : if Assigned(FOnDVDErrorUnexpected) then FOnDVDErrorUnexpected(self);
  1861.             2 : if Assigned(FOnDVDErrorCopyProtectFail) then FOnDVDErrorCopyProtectFail(self);
  1862.             3 : if Assigned(FOnDVDErrorInvalidDVD1_0Disc) then FOnDVDErrorInvalidDVD1_0Disc(self);
  1863.             4 : if Assigned(FOnDVDErrorInvalidDiscRegion) then FOnDVDErrorInvalidDiscRegion(self);
  1864.             5 : if Assigned(FOnDVDErrorLowParentalLevel) then FOnDVDErrorLowParentalLevel(self);
  1865.             6 : if Assigned(FOnDVDErrorMacrovisionFail) then FOnDVDErrorMacrovisionFail(self);
  1866.             7 : if Assigned(FOnDVDErrorIncompatibleSystemAndDecoderRegions) then FOnDVDErrorIncompatibleSystemAndDecoderRegions(self);
  1867.             8 : if Assigned(FOnDVDErrorIncompatibleDiscAndDecoderRegions) then FOnDVDErrorIncompatibleDiscAndDecoderRegions(self);
  1868.           end;
  1869.         end;
  1870.       EC_DVD_NO_FP_PGC               : if Assigned(FOnDVDNoFP_PGC) then FOnDVDNoFP_PGC(self);
  1871.       EC_DVD_STILL_OFF               : if Assigned(FOnDVDStillOff) then FOnDVDStillOff(self);
  1872.       EC_DVD_STILL_ON                : if Assigned(FOnDVDStillOn) then FOnDVDStillOn(self,(Param1 = 1), Param2);
  1873.       EC_DVD_SUBPICTURE_STREAM_CHANGE:
  1874.         begin
  1875.           if Assigned(FOnDVDSubpictureStreamChange) then
  1876.           begin
  1877.             DvdInfo2.GetSubpictureLanguage(Param1,lcid);
  1878.             GetLocaleInfo(lcid,LOCALE_SENGLANGUAGE,achLang,MAX_PATH);
  1879.             FOnDVDSubpictureStreamChange(self,Param1,lcid,string(achLang));
  1880.           end;
  1881.         end;
  1882.       EC_DVD_TITLE_CHANGE            : if Assigned(FOnDVDTitleChange) then FOnDVDTitleChange(self,Param1);
  1883.       EC_DVD_VALID_UOPS_CHANGE       : if Assigned(FOnDVDValidUOPSChange) then FOnDVDValidUOPSChange(self, Param1);
  1884.       EC_DVD_WARNING                 :
  1885.         begin
  1886.           case Param1 of
  1887.             1 : if Assigned(FOnDVDWarningInvalidDVD1_0Disc)  then FOnDVDWarningInvalidDVD1_0Disc(self);
  1888.             2 : if Assigned(FOnDVDWarningFormatNotSupported) then FOnDVDWarningFormatNotSupported(self);
  1889.             3 : if Assigned(FOnDVDWarningIllegalNavCommand)  then FOnDVDWarningIllegalNavCommand(self);
  1890.             4 : if Assigned(FOnDVDWarningOpen)  then FOnDVDWarningOpen(self);
  1891.             5 : if Assigned(FOnDVDWarningSeek)  then FOnDVDWarningSeek(self);
  1892.             6 : if Assigned(FOnDVDWarningRead)  then FOnDVDWarningRead(self);
  1893.           end;
  1894.         end;
  1895.       EC_DVD_PLAYBACK_RATE_CHANGE    : if Assigned(FOnDVDPlaybackRateChange) then FOnDVDPlaybackRateChange(self, Param1/10000);
  1896.       EC_DVD_PARENTAL_LEVEL_CHANGE   : if Assigned(FOnDVDParentalLevelChange) then FOnDVDParentalLevelChange(self,Param1);
  1897.       EC_DVD_PLAYBACK_STOPPED        : if Assigned(FOnDVDPlaybackStopped) then FOnDVDPlaybackStopped(self);
  1898.       EC_DVD_ANGLES_AVAILABLE        : if Assigned(FOnDVDAnglesAvailable) then FOnDVDAnglesAvailable(self,(Param1 = 1));
  1899.       EC_DVD_PLAYPERIOD_AUTOSTOP     : if Assigned(FOnDVDPlayPeriodAutoStop) then FOnDVDPlayPeriodAutoStop(self);
  1900.       EC_DVD_BUTTON_AUTO_ACTIVATED   : if Assigned(FOnDVDButtonAutoActivated) then FOnDVDButtonAutoActivated(self,Param1);
  1901.       EC_DVD_CMD_START               : if Assigned(FOnDVDCMDStart) then FOnDVDCMDStart(self,Param1);
  1902.       EC_DVD_CMD_END                 : if Assigned(FOnDVDCMDEnd) then FOnDVDCMDEnd(self,Param1);
  1903.       EC_DVD_DISC_EJECTED            : if Assigned(FOnDVDDiscEjected) then FOnDVDDiscEjected(self);
  1904.       EC_DVD_DISC_INSERTED           : if Assigned(FOnDVDDiscInserted) then FOnDVDDiscInserted(self);
  1905.       EC_DVD_CURRENT_HMSF_TIME       :
  1906.         begin
  1907.           if assigned(FOnDVDCurrentHMSFTime) then
  1908.             begin
  1909.               hmsftc := TDVDHMSFTimeCode(param1);
  1910.               tc := IntToTimeCode(Param2);
  1911.               FOnDVDCurrentHMSFTime(self,hmsftc,tc);
  1912.             end;
  1913.         end;
  1914.       EC_DVD_KARAOKE_MODE            : if assigned(FOnDVDKaraokeMode) then FOnDVDKaraokeMode(self,BOOL(Param1));
  1915.     end;
  1916.   end;
  1917.  
  1918.   function TFilterGraph.QueryInterface(const IID: TGUID; out Obj): HResult;
  1919.   begin
  1920.     result := inherited QueryInterface(IID, Obj);
  1921.     if (not Succeeded(result)) and Active then
  1922.     case FMode of
  1923.       gmNormal  : result := FFilterGraph.QueryInterface(IID, Obj);
  1924.       gmCapture : begin
  1925.                     result := FCaptureGraph.QueryInterface(IID, Obj);
  1926.                     if not Succeeded(result) then result := FFilterGraph.QueryInterface(IID, Obj);
  1927.                   end;
  1928.       gmDVD     : begin
  1929.                     result := FDvdGraph.QueryInterface(IID, Obj);
  1930.                     if not Succeeded(result) then result := FDvdGraph.GetDvdInterface(IID, Obj);
  1931.                     if not Succeeded(result) then result := FFilterGraph.QueryInterface(IID, Obj);
  1932.                   end;
  1933.     end;
  1934.   end;
  1935.  
  1936.   procedure TFilterGraph.SetGraphEdit(enable: boolean);
  1937.   begin
  1938.     case enable of
  1939.       true  :
  1940.         begin
  1941.           if FGraphEditID = 0 then
  1942.             if Active then
  1943.               AddGraphToRot(IFilterGraph2(FFilterGraph) , FGraphEditID);
  1944.         end;
  1945.       false :
  1946.         begin
  1947.           if FGraphEditID <> 0 then
  1948.           begin
  1949.             RemoveGraphFromRot(FGraphEditID);
  1950.             FGraphEditID := 0;
  1951.           end;
  1952.         end;
  1953.     end;
  1954.     FGraphEdit := enable;
  1955.   end;
  1956.  
  1957.   procedure TFilterGraph.InsertFilter(AFilter: IFilter);
  1958.   var FilterName: WideString;
  1959.   begin
  1960.     if FFilters = nil then FFilters := TInterfaceList.Create;
  1961.     FFilters.Add(AFilter);
  1962.     if active then
  1963.       begin
  1964.         AFilter.NotifyFilter(foAdding);
  1965.         FilterName := AFilter.GetName;
  1966.         FFilterGraph.AddFilter(AFilter.GetFilter, PWideChar(FilterName));
  1967.         AFilter.NotifyFilter(foAdded);
  1968.       end;
  1969.   end;
  1970.  
  1971.   procedure TFilterGraph.RemoveFilter(AFilter: IFilter);
  1972.   begin
  1973.     FFilters.Remove(AFilter);
  1974.     if active then
  1975.       begin
  1976.         AFilter.NotifyFilter(foRemoving);
  1977.         FFilterGraph.RemoveFilter(AFilter.GetFilter);
  1978.         AFilter.NotifyFilter(foRemoved);
  1979.       end;
  1980.     if FFilters.Count = 0 then
  1981.        FreeAndNil(FFilters);
  1982.   end;
  1983.  
  1984.   procedure TFilterGraph.InsertEventNotifier(AEvent: IEvent);
  1985.   begin
  1986.     if FGraphEvents = nil then FGraphEvents := TInterFaceList.Create;
  1987.     FGraphEvents.Add(AEvent);
  1988.   end;
  1989.  
  1990.   procedure TFilterGraph.RemoveEventNotifier(AEvent: IEvent);
  1991.   begin
  1992.     if FGraphEvents <> nil then
  1993.     begin
  1994.       FGraphEvents.Remove(AEvent);
  1995.       if FGraphEvents.Count = 0 then FreeAndNil(FGraphEvents);
  1996.     end;
  1997.   end;
  1998.  
  1999.   procedure TFilterGraph.ClearOwnFilters;
  2000.   var i: integer;
  2001.   begin
  2002.     if Active and (FFilters <> nil) then
  2003.       for i := 0 to FFilters.Count - 1 do
  2004.         begin
  2005.           IFilter(FFilters.Items[i]).NotifyFilter(foRemoving);
  2006.           FFilterGraph.RemoveFilter(IFilter(FFilters.Items[i]).GetFilter);
  2007.           IFilter(FFilters.Items[i]).NotifyFilter(foRemoved);
  2008.         end;
  2009.   end;
  2010.  
  2011.   procedure TFilterGraph.AddOwnFilters;
  2012.   var
  2013.     i: integer;
  2014.     FilterName: WideString;
  2015.   begin
  2016.     if Active and (FFilters <> nil) then
  2017.       for i := 0 to FFilters.Count - 1 do
  2018.         begin
  2019.           IFilter(FFilters.Items[i]).NotifyFilter(foAdding);
  2020.           FilterName := IFilter(FFilters.Items[i]).GetName;
  2021.           FFilterGraph.AddFilter(IFilter(FFilters.Items[i]).GetFilter, PWideChar(FilterName));
  2022.           IFilter(FFilters.Items[i]).NotifyFilter(foAdded);
  2023.         end;
  2024.   end;
  2025.  
  2026. {
  2027.   procedure TFilterGraph.NotifyFilters(operation: TFilterOperation; Param: integer);
  2028.   var i: integer;
  2029.   begin
  2030.     if FFilters <> nil then
  2031.       for i := 0 to FFilters.Count - 1 do
  2032.         IFilter(FFilters.Items[i]).NotifyFilter(operation, Param);
  2033.  
  2034.   end;
  2035. }
  2036.  
  2037.   procedure TFilterGraph.GraphEvents(Event, Param1, Param2: integer);
  2038.   var i: integer;
  2039.   begin
  2040.     if FGraphEvents <> nil then
  2041.       for i := 0 to FGraphEvents.Count - 1 do
  2042.          IEvent(FGraphEvents.Items[i]).GraphEvent(Event, Param1, Param2);
  2043.   end;
  2044.  
  2045.   procedure TFilterGraph.ControlEvents(Event: TControlEvent; Param: integer = 0);
  2046.   var i: integer;
  2047.   begin
  2048.     if FGraphEvents <> nil then
  2049.       for i := 0 to FGraphEvents.Count - 1 do
  2050.          IEvent(FGraphEvents.Items[i]).ControlEvent(Event, param);
  2051.   end;
  2052.  
  2053.   function TFilterGraph.Play: boolean;
  2054.   var MediaControl: IMediaControl;
  2055.   begin
  2056.     result := false;
  2057.     if Succeeded(QueryInterface(IMediaControl, MediaControl)) then
  2058.     begin
  2059.       ControlEvents(cePlay);
  2060.       result := Succeeded((CheckDSError(MediaControl.Run)));
  2061.       MediaControl := nil;
  2062.     end;
  2063.   end;
  2064.  
  2065.   function TFilterGraph.Pause: boolean;
  2066.   var MediaControl: IMediaControl;
  2067.   begin
  2068.     result := false;
  2069.     if Succeeded(QueryInterface(IMediaControl, MediaControl)) then
  2070.     begin
  2071.       ControlEvents(cePause);
  2072.       result := (CheckDSError(MediaControl.Pause) = S_OK);
  2073.       MediaControl := nil;
  2074.     end;
  2075.   end;
  2076.  
  2077.   function TFilterGraph.Stop: boolean;
  2078.   var MediaControl: IMediaControl;
  2079.   begin
  2080.     result := false;
  2081.     if Succeeded(QueryInterface(IMediaControl, MediaControl)) then
  2082.     begin
  2083.       ControlEvents(ceStop);
  2084.       result := (CheckDSError(MediaControl.Stop) = S_OK);
  2085.       MediaControl := nil;
  2086.     end;
  2087.   end;
  2088.  
  2089.   procedure TFilterGraph.SetLogFile(FileName: String);
  2090.   begin
  2091.     if Active then
  2092.     begin
  2093.       FFilterGraph.SetLogFile(0);
  2094.       if Assigned(FLogFile) then FreeAndNil(FLogFile);
  2095.       if FileName <> '' then
  2096.       try
  2097.         
  2098.         FLogFile := TFileStream.Create(FileName, fmCreate{$IFDEF VER140}, fmShareDenyNone{$ENDIF});
  2099.         
  2100.         FFilterGraph.SetLogFile(FLogFile.Handle);
  2101.       except
  2102.         FFilterGraph.SetLogFile(0);
  2103.         if Assigned(FLogFile) then FreeAndNil(FLogFile);
  2104.         exit;
  2105.       end;
  2106.     end;
  2107.     FLogFileName := FileName;
  2108.   end;
  2109.  
  2110.   procedure TFilterGraph.DisconnectFilters;
  2111.   var
  2112.     FilterList: TFilterList;
  2113.     PinList: TPinList;
  2114.     BaseFilter: IBaseFilter;
  2115.     i, j: integer;
  2116.   begin
  2117.     if assigned(FFilterGraph) then
  2118.     begin
  2119.       FilterList:= TFilterList.Create(FFilterGraph);
  2120.       if FilterList.Count > 0 then
  2121.         for i := 0 to FilterList.Count - 1 do
  2122.           begin
  2123.             BaseFilter := FilterList.Items[i] as IBaseFilter;
  2124.             PinList := TPinList.Create(BaseFilter);
  2125.             if PinList.Count > 0 then
  2126.             for j := 0 to PinList.Count - 1 do
  2127.               CheckDSError(IPin(PinList.Items[j]).Disconnect);
  2128.             PinList.Free;
  2129.             BaseFilter := nil;
  2130.           end;
  2131.       FilterList.Free;
  2132.     end;
  2133.   end;
  2134.  
  2135.   procedure TFilterGraph.ClearGraph;
  2136.   var
  2137.     i: integer;
  2138.     FilterList: TFilterList;
  2139.   begin
  2140.     if Assigned(FFilterGraph) then
  2141.     begin
  2142.       Stop;
  2143.       DisconnectFilters;
  2144.       FilterList:= TFilterList.Create(FFilterGraph);
  2145.       if assigned(FFilters) then
  2146.         if FFilters.Count > 0 then
  2147.           for i := 0 to FFilters.count - 1 do
  2148.             FilterList.Remove(IFilter(FFilters.Items[i]).GetFilter);
  2149.       if FilterList.count > 0 then
  2150.       for i := 0 to FilterList.Count - 1 do
  2151.         CheckDSError(FFilterGraph.RemoveFilter(FilterList.Items[i]));
  2152.       FilterList.Free;
  2153.     end;
  2154.   end;
  2155.  
  2156.   function TFilterGraph.GetState: TGraphState;
  2157.   var
  2158.     AState: TFilterState;
  2159.     MediaControl: IMediaControl;
  2160.   begin
  2161.     result := gsUninitialized;
  2162.     if Succeeded(QueryInterface(IMediaControl, MediaControl)) then
  2163.     begin
  2164.       MediaControl.GetState(0,AState);
  2165.       case AState of
  2166.         State_Stopped : result := gsStopped;
  2167.         State_Paused  : result := gsPaused;
  2168.         State_Running : result := gsPlaying;
  2169.       end;
  2170.       MediaControl := nil;
  2171.     end;
  2172.   end;
  2173.  
  2174.   function TFilterGraph.GetVolume: integer;
  2175.   var
  2176.     BasicAudio: IBasicAudio;
  2177.     AVolume: integer;
  2178.   begin
  2179.     result := 0;
  2180.     if Succeeded(QueryInterface(IBasicAudio, BasicAudio)) then
  2181.     begin
  2182.       BasicAudio.get_Volume(AVolume);
  2183.       result := AVolume + 10000;
  2184.       BasicAudio := nil;
  2185.     end;
  2186.   end;
  2187.  
  2188.   procedure TFilterGraph.SetVolume(Volume: Integer);
  2189.   var
  2190.     BasicAudio: IBasicAudio;
  2191.   begin
  2192.     if Succeeded(QueryInterface(IBasicAudio, BasicAudio)) then
  2193.     begin
  2194.       BasicAudio.put_Volume(Volume-10000);
  2195.       BasicAudio := nil;
  2196.     end;
  2197.   end;
  2198.  
  2199.   function TFilterGraph.GetBalance: integer;
  2200.   var
  2201.     BasicAudio: IBasicAudio;
  2202.   begin
  2203.     if Succeeded(QueryInterface(IBasicAudio, BasicAudio)) then
  2204.     begin
  2205.       BasicAudio.get_Balance(result);
  2206.       BasicAudio := nil;
  2207.     end;
  2208.   end;
  2209.  
  2210.   procedure TFilterGraph.SetBalance(Balance: integer);
  2211.   var BasicAudio: IBasicAudio;
  2212.   begin
  2213.     if Succeeded(QueryInterface(IBasicAudio, BasicAudio)) then
  2214.     begin
  2215.       BasicAudio.put_Balance(Balance);
  2216.       BasicAudio := nil;
  2217.     end;
  2218.   end;
  2219.  
  2220.   function TFilterGraph.GetSeekCaps: TSeekingCaps;
  2221.   var
  2222.     MediaSeeking: IMediaSeeking;
  2223.     Flags: Cardinal;
  2224.   begin
  2225.     result := [];
  2226.     if Succeeded(QueryInterface(IMediaSeeking, MediaSeeking)) then
  2227.     begin
  2228.       MediaSeeking.GetCapabilities(Flags);
  2229.       PByte(@Result)^ := Flags;
  2230.       MediaSeeking := nil;
  2231.     end;
  2232.   end;
  2233.  
  2234.   function TFilterGraph.RenderFile(FileName: WideString): HRESULT;
  2235.   begin
  2236.     result := S_FALSE;
  2237.     if assigned(FFilterGraph) then
  2238.     begin
  2239.       ControlEvents(ceFileRendering);
  2240.       result := CheckDSError(FFilterGraph.RenderFile(PWideChar(FileName), nil));
  2241.       if Succeeded(result) then ControlEvents(ceFileRendered);
  2242.     end;
  2243.   end;
  2244.  
  2245.   { TODO -oHG : Add the audio rendering }
  2246.   function TFilterGraph.RenderFileEx(FileName: WideString): HRESULT;
  2247.   var
  2248.     SourceFilter: IBaseFilter;
  2249.     PinList: TPinList;
  2250.     i: Integer;
  2251.   begin
  2252.     result := S_FALSE;
  2253.     if assigned(FFilterGraph) then
  2254.     begin
  2255.       ControlEvents(ceFileRendering);
  2256.       CheckDSError(FFilterGraph.AddSourceFilter(PWideChar(FileName), PWideChar(FileName), SourceFilter));
  2257.       PinList := TPinList.Create(SourceFilter);
  2258.       try
  2259.         for i := 0 to PinList.Count - 1 do
  2260.         begin
  2261.           CheckDSError(IFilterGraph2(FFilterGraph).RenderEx(PinList.Items[i],
  2262.             AM_RENDEREX_RENDERTOEXISTINGRENDERERS, nil));
  2263.         end;
  2264.       finally
  2265.         PinList.Free;
  2266.       end;
  2267.       if Succeeded(result) then ControlEvents(ceFileRendered);
  2268.     end;
  2269.   end;
  2270.  
  2271.   function TFilterGraph.RenderDVD(out status: TAMDVDRenderStatus;
  2272.     FileName: WideString = ''; Mode: Integer = AM_DVD_HWDEC_PREFER): HRESULT;
  2273.   begin
  2274.     result := HRESULT(VFW_E_DVD_RENDERFAIL);
  2275.     if assigned(FDVDGraph) then
  2276.     begin
  2277.       ControlEvents(ceDVDRendering, Mode);
  2278.       if FileName <> '' then
  2279.         result := CheckDSError(FDVDGraph.RenderDvdVideoVolume(PWideChar(FileName), Mode, Status))
  2280.       else
  2281.         result := CheckDSError(FDVDGraph.RenderDvdVideoVolume(nil, Mode, Status));
  2282.       if result in [S_OK..S_FALSE] then ControlEvents(ceDVDRendered, Mode);
  2283.     end;
  2284.   end;
  2285.  
  2286.   procedure TFilterGraph.SetRate(Rate: double);
  2287.   var MediaSeeking: IMediaSeeking;
  2288.   begin
  2289.     if Succeeded(QueryInterface(IMediaSeeking, MediaSeeking)) then
  2290.     begin
  2291.       MediaSeeking.SetRate(Rate);
  2292.       MediaSeeking := nil;
  2293.     end;
  2294.   end;
  2295.  
  2296.   function TFilterGraph.GetRate: double;
  2297.   var MediaSeeking: IMediaSeeking;
  2298.   begin
  2299.     if Succeeded(QueryInterface(IMediaSeeking, MediaSeeking)) then
  2300.     begin
  2301.       MediaSeeking.GetRate(result);
  2302.       MediaSeeking := nil;
  2303.     end;
  2304.   end;
  2305.  
  2306.   function TFilterGraph.GetDuration: integer;
  2307.   var
  2308.     MediaSeeking: IMediaSeeking;
  2309.     RefTime: int64;
  2310.   begin
  2311.     if Succeeded(QueryInterface(IMediaSeeking, MediaSeeking)) then
  2312.     begin
  2313.       MediaSeeking.GetDuration(RefTime);
  2314.       result := RefTimeToMiliSec(RefTime);
  2315.       MediaSeeking := nil;
  2316.     end
  2317.     else
  2318.       result := 0;
  2319.   end;
  2320.  
  2321.   procedure TFilterGraph.DVDSaveBookmark(BookMarkFile: WideString);
  2322.   var
  2323.     DVDInfo2: IDVDInfo2;
  2324.     Bookmark: IDvdState;
  2325.     pStorage: IStorage;
  2326.     pStream : IStream;
  2327.     PersistStream : IPersistStream;
  2328.   begin
  2329.     if Active and (Mode = gmDVD) then
  2330.     if Succeeded(QueryInterface(IDVDInfo2, DVDInfo2)) then
  2331.     begin
  2332.       DVDInfo2.GetState(Bookmark);
  2333.       StgCreateDocfile(PWideChar(BookMarkFile), STGM_CREATE or STGM_WRITE or STGM_SHARE_EXCLUSIVE, 0, pStorage);
  2334.       pStorage.CreateStream('BookMark', STGM_CREATE or STGM_WRITE or STGM_SHARE_EXCLUSIVE, 0, 0, pStream);
  2335.       if Succeeded(Bookmark.QueryInterface(IID_IPersistStream,PersistStream)) then
  2336.         begin
  2337.           OleSaveToStream(PersistStream,pStream);
  2338.           PersistStream := nil;
  2339.        end
  2340.        else
  2341.        begin
  2342.          PersistStream := nil;
  2343.          DVDInfo2      := nil;
  2344.          exit;
  2345.        end;
  2346.      DVDInfo2 := nil;
  2347.     end;
  2348.   end;
  2349.  
  2350.   procedure TFilterGraph.DVDRestoreBookmark(BookMarkFile: WideString);
  2351.   var
  2352.     DVDControl2: IDvdControl2;
  2353.     pStorage : IStorage;
  2354.     pStream  : IStream;
  2355.     pBookmark: IDvdState;
  2356.     hr       : HRESULT;
  2357.     obj      : IDVDCmd;
  2358.   begin
  2359.     if Succeeded(QueryInterface(IDvdControl2, DvdControl2)) then
  2360.     begin
  2361.       StgOpenStorage(PWideChar(BookMarkFile), nil, STGM_READ or STGM_SHARE_EXCLUSIVE, nil , 0, pStorage);
  2362.       pStorage.OpenStream('BookMark', nil, STGM_READ or STGM_SHARE_EXCLUSIVE, 0, pStream);
  2363.       OleLoadFromStream(pStream, IID_IDvdState, pBookmark);
  2364.       hr := CheckDSError(DVDControl2.SetState(pBookmark, DVD_CMD_FLAG_None, obj));
  2365.       if not (failed(hr)) then
  2366.         begin
  2367.           obj.WaitForEnd;
  2368.           obj := nil;
  2369.         end;
  2370.       DvdControl2 := nil;
  2371.     end;
  2372.   end;
  2373.  
  2374.  
  2375. //******************************************************************************
  2376. // TVMROptions
  2377. //******************************************************************************
  2378.  
  2379.   constructor TVMROptions.Create(AOwner: TVideoWindow);
  2380.   begin
  2381.     FPreferences := [vpForceMixer];
  2382.     FStreams := 4;
  2383.     FOwner   := AOwner;
  2384.     FMode    := vmrWindowed;
  2385.     FKeepAspectRatio := True;
  2386.   end;
  2387.  
  2388.   procedure TVMROptions.SetStreams(Streams: cardinal);
  2389.   begin
  2390.     if Streams in [1..16] then FStreams := Streams else FStreams := 1;
  2391.     with FOwner do
  2392.     begin
  2393.       if (mode <> vmVMR) or (FilterGraph = nil) then exit;
  2394.       if not FilterGraph.Active then exit;
  2395.       // need to reconnect
  2396.       FilterGraph.RemoveFilter(FOwner);
  2397.       FilterGraph.InsertFilter(FOwner);
  2398.     end;
  2399.   end;
  2400.  
  2401.   procedure TVMROptions.SetPreferences(Preferences: TVMRPreferences);
  2402.   begin
  2403.     FPreferences := Preferences;
  2404.     with FOwner do
  2405.     begin
  2406.       if (mode <> vmVMR) or (FilterGraph = nil) then exit;
  2407.       if not FilterGraph.Active then exit;
  2408.       // need to reconnect
  2409.       FilterGraph.RemoveFilter(FOwner);
  2410.       FilterGraph.InsertFilter(FOwner);
  2411.     end;
  2412.   end;
  2413.  
  2414.   procedure TVMROptions.SetMode(AMode: TVMRVideoMode);
  2415.   begin
  2416.     FMode := AMode;
  2417.     with FOwner do
  2418.     begin
  2419.       if (mode <> vmVMR) or (FilterGraph = nil) then exit;
  2420.       if not FilterGraph.Active then exit;
  2421.       // need to reconnect
  2422.       FilterGraph.RemoveFilter(FOwner);
  2423.       FilterGraph.InsertFilter(FOwner);
  2424.     end;
  2425.   end;
  2426.  
  2427.   procedure TVMROptions.SetKeepAspectRatio(Keep: boolean);
  2428.   var AspectRatioControl: IVMRAspectRatioControl9;
  2429.   begin
  2430.     FKeepAspectRatio := Keep;
  2431.     case Mode of
  2432.       vmrWindowed, vmrWindowless:
  2433.         begin
  2434.           if Succeeded(FOwner.QueryInterface(IVMRAspectRatioControl9, AspectRatioControl)) then
  2435.           case Keep of
  2436.             true: CheckDSError(AspectRatioControl.SetAspectRatioMode(VMR_ARMODE_LETTER_BOX));
  2437.             false: CheckDSError(AspectRatioControl.SetAspectRatioMode(VMR_ARMODE_NONE));
  2438.           end;
  2439.  
  2440.         end;
  2441.       vmrRenderless: {TODO};
  2442.     end;
  2443.   end;
  2444.  
  2445.  
  2446. //******************************************************************************
  2447. // TVideoWindow
  2448. //******************************************************************************
  2449.  
  2450.   constructor TVideoWindow.Create(AOwner: TComponent);
  2451.   begin
  2452.     inherited Create(AOwner);
  2453.     FVMROptions:= TVMROptions.Create(self);
  2454.     ControlStyle := [csAcceptsControls, csCaptureMouse, csClickEvents,
  2455.     csDoubleClicks, csReflector];
  2456.     TabStop   := true;
  2457.     Height    := 120;
  2458.     Width     := 160;
  2459.     color     := $000000;
  2460.     FIsFullScreen := false;
  2461.     FKeepAspectRatio := True;
  2462.   end;
  2463.  
  2464.   destructor TVideoWindow.Destroy;
  2465.   begin
  2466.     FVMROptions.Free;
  2467.     FilterGraph := nil;
  2468.     inherited destroy;
  2469.   end;
  2470.  
  2471.   procedure TVideoWindow.SetVideoMode(AMode: TVideoMode);
  2472.   begin
  2473.     if (AMode = vmVMR) and (not CheckVMR)
  2474.       then FMode := vmNormal
  2475.       else FMode := AMode;
  2476.     if FilterGraph = nil then exit;
  2477.     if not FilterGraph.Active then exit;
  2478.     // need to reconnect
  2479.     FilterGraph.RemoveFilter(self);
  2480.     FilterGraph.InsertFilter(self);
  2481.   end;
  2482.  
  2483.   procedure TVideoWindow.Loaded;
  2484.   begin
  2485.     inherited Loaded;
  2486.     FWindowStyle   := GetWindowLong(Handle, GWL_STYLE);
  2487.     FWindowStyleEx := GetWindowLong(Handle, GWL_EXSTYLE);
  2488.   end;
  2489.  
  2490.   procedure TVideoWindow.Notification(AComponent: TComponent;
  2491.     Operation: TOperation);
  2492.   begin
  2493.     inherited Notification(AComponent, Operation);
  2494.     if ((AComponent = FFilterGraph) and (Operation = opRemove)) then
  2495.         FFilterGraph := nil;
  2496.   end;
  2497.  
  2498.   procedure TVideoWindow.SetFilterGraph(AFilterGraph: TFilterGraph);
  2499.   begin
  2500.     if AFilterGraph = FFilterGraph then exit;
  2501.     if FFilterGraph <> nil then
  2502.     begin
  2503.       FFilterGraph.RemoveFilter(self);
  2504.       FFilterGraph.RemoveEventNotifier(self);
  2505.     end;
  2506.     if AFilterGraph <> nil then
  2507.     begin
  2508.       AFilterGraph.InsertFilter(self);
  2509.       AFilterGraph.InsertEventNotifier(self);
  2510.     end;
  2511.     FFilterGraph := AFilterGraph;
  2512.   end;
  2513.  
  2514.   function TVideoWindow.GetFilter: IBaseFilter;
  2515.   begin
  2516.     result := FBaseFilter;
  2517.   end;
  2518.  
  2519.   function TVideoWindow.GetName: string;
  2520.   begin
  2521.     result := name;
  2522.   end;
  2523.  
  2524.   procedure TVideoWindow.NotifyFilter(operation: TFilterOperation; Param: integer);
  2525.   var
  2526.     EnumPins: TPinList;
  2527.     VMRFilterConfig: IVMRFilterConfig9;
  2528.     VMRSurfaceAllocatorNotify: IVMRSurfaceAllocatorNotify9;
  2529.     VMRSurfaceAllocator: IVMRSurfaceAllocator9;
  2530.     MyPrefs: TVMRPreferences;
  2531.     APrefs: cardinal;
  2532.     i: integer;
  2533.     CW: Word;
  2534.     hr: HResult;
  2535.     DSPackException: EDSPackException;
  2536.  
  2537.     procedure UpdatePreferences;
  2538.     begin
  2539.       // VMR9 preferences
  2540.       MyPrefs := FVMROptions.FPreferences - [vpForceMixer];
  2541.       CheckDSError(VMRFilterConfig.SetRenderingPrefs(PByte(@MyPrefs)^));
  2542.       APrefs := 0;
  2543.       CheckDSError(VMRFilterConfig.GetRenderingPrefs(APrefs));
  2544.       if (vpForceMixer in FVMROptions.FPreferences) then
  2545.         FVMROptions.FPreferences := PVMRPreferences(@APrefs)^ + [vpForceMixer]
  2546.       else
  2547.         FVMROptions.FPreferences := PVMRPreferences(@APrefs)^;
  2548.     end;
  2549.   begin
  2550.     case operation of
  2551.       foAdding:
  2552.         begin
  2553.           case mode of
  2554.             vmVMR    :
  2555.               begin
  2556.                 CW := Get8087CW;
  2557.                 try
  2558.                   CoCreateInstance(CLSID_VideoMixingRenderer9, nil, CLSCTX_INPROC, IID_IBaseFilter ,FBaseFilter);
  2559.                   FBaseFilter.QueryInterface(IVMRFilterConfig9, VMRFilterConfig);
  2560.                   case FVMROptions.Mode of
  2561.                   vmrWindowed: CheckDSError(VMRFilterConfig.SetRenderingMode(VMR9Mode_Windowed));
  2562.                   vmrWindowless: CheckDSError(VMRFilterConfig.SetRenderingMode(VMR9Mode_Windowless));
  2563.                   vmrRenderless:
  2564.                     begin
  2565.                       if (FAllocatorClass = nil) then
  2566.                         raise EDSPackException.Create('Allocator class not set.');
  2567.  
  2568.                       FCurrentAllocator := FAllocatorClass.Create(hr, Handle);
  2569.                       if failed(hr) then
  2570.                       begin
  2571.                         DSPackException := EDSPackException.Create('Error Creating Allocator');
  2572.                         DSPackException.ErrorCode := hr;
  2573.                         raise DSPackException;
  2574.                       end;
  2575.  
  2576.                       CheckDSError(VMRFilterConfig.SetRenderingMode(VMR9Mode_Renderless));
  2577.                       CheckDSError(FBaseFilter.QueryInterface(IID_IVMRSurfaceAllocatorNotify9, VMRSurfaceAllocatorNotify));
  2578.                       CheckDSError(FCurrentAllocator.QueryInterface(IID_IVMRSurfaceAllocator9, VMRSurfaceAllocator));
  2579.  
  2580.                       VMRSurfaceAllocatorNotify.AdviseSurfaceAllocator(FRenderLessUserID, VMRSurfaceAllocator);
  2581.                       VMRSurfaceAllocator._AddRef; // manual increment;
  2582.                       VMRSurfaceAllocator.AdviseNotify(VMRSurfaceAllocatorNotify);
  2583.                     end;
  2584.                   end;
  2585.                   VMRFilterConfig := nil;
  2586.                 finally
  2587.                   Set8087CW(CW);
  2588.                 end;
  2589.               end;
  2590.             vmNormal : CoCreateInstance(CLSID_VideoRenderer, nil, CLSCTX_INPROC_SERVER, IID_IBaseFilter ,FBaseFilter);
  2591.           end;
  2592.         end;
  2593.       foAdded:
  2594.         begin
  2595.           case mode of
  2596.             vmVMR:
  2597.               begin
  2598.                 if (FBaseFilter <> nil) then
  2599.                   if CheckDSError(FBaseFilter.QueryInterface(IVMRFilterConfig9, VMRFilterConfig)) = S_OK then
  2600.                   begin
  2601.                     if (FVMROptions.FStreams <> 4)
  2602.                       or (vpForceMixer in FVMROptions.FPreferences) then
  2603.                     begin
  2604.                       CheckDSError(VMRFilterConfig.SetNumberOfStreams(FVMROptions.FStreams));
  2605.                       CheckDSError(VMRFilterConfig.GetNumberOfStreams(FVMROptions.FStreams));
  2606.                     end;
  2607.  
  2608.  
  2609.                     case FVMROptions.Mode of
  2610.                       vmrWindowed   :
  2611.                         begin
  2612.  
  2613.                           CheckDSError(FBaseFilter.QueryInterface(IVideoWindow, FVideoWindow));
  2614.                           UpdatePreferences;
  2615.                         end;
  2616.                       vmrWindowless :
  2617.                         begin
  2618.  
  2619.                           CheckDSError(FBaseFilter.QueryInterface(IVMRWindowlessControl9, FWindowLess));
  2620.                           CheckDSError(FWindowLess.SetVideoClippingWindow(Handle));
  2621.                           UpdatePreferences;
  2622.                           Resize;
  2623.                         end;
  2624.                       vmrRenderless :
  2625.                         begin
  2626.                           //Assert(False, 'not yet imlemented.');
  2627.                           //CheckDSError(FBaseFilter.QueryInterface(IVMRWindowlessControl9, FWindowLess));
  2628.                           //CheckDSError(FWindowLess.SetVideoClippingWindow(Handle));
  2629.                         end;
  2630.  
  2631.                     end;
  2632.                     VMRFilterConfig := nil;
  2633.                     VMROptions.SetKeepAspectRatio(VMROptions.FKeepAspectRatio);
  2634.                   end;
  2635.               end;
  2636.             vmNormal: CheckDSError(FBaseFilter.QueryInterface(IVideoWindow, FVideoWindow));
  2637.           end;
  2638.         end;
  2639.       foRemoving:
  2640.         if FBaseFilter <> nil then
  2641.           begin
  2642.             // it's important to stop and disconnect the filter before removing the VMR filter.
  2643.             CheckDSError(FBaseFilter.Stop);
  2644.             EnumPins := TPinList.Create(FBaseFilter);
  2645.             if EnumPins.Count > 0 then
  2646.               for i := 0 to EnumPins.Count - 1 do
  2647.                 CheckDSError(EnumPins.Items[i].Disconnect);
  2648.             EnumPins.Free;
  2649.             if (FCurrentAllocator <> nil) and (mode = vmVMR) and (VMROptions.Mode = vmrRenderless) then
  2650.             begin
  2651.               IUnKnown(FCurrentAllocator)._Release;
  2652.               FCurrentAllocator := nil;
  2653.             end;
  2654.           end;
  2655.       foRemoved :
  2656.         begin
  2657.           FVideoWindow     := nil;
  2658.           FWindowLess      := nil;
  2659.           FBaseFilter      := nil;
  2660.         end;
  2661.     end;
  2662.   end;
  2663.  
  2664.   procedure TVideoWindow.Paint;
  2665.   begin
  2666.     inherited Paint;
  2667.     if Assigned(FOnPaint) then FOnPaint(self);
  2668.   end;
  2669.  
  2670.   procedure TVideoWindow.Resize;
  2671.   var ARect: TRect;
  2672.   begin
  2673.     inherited Resize;
  2674.     case FMode of
  2675.       vmNormal:
  2676.         begin
  2677.           if (FVideoWindow <> nil) and (not FullScreen) then
  2678.             FVideoWindow.SetWindowPosition(Left,Top,Width,Height);
  2679.         end;
  2680.       vmVMR:
  2681.         case FVMROptions.Mode of
  2682.           vmrWindowed:
  2683.             begin
  2684.               if (FVideoWindow <> nil) and (not FullScreen) then
  2685.                 FVideoWindow.SetWindowPosition(Left,Top,Width,Height);
  2686.             end;
  2687.           vmrWindowless:
  2688.             if FWindowLess <> nil then
  2689.             begin
  2690.               ARect := Rect(0,0, width, height);
  2691.               FWindowLess.SetVideoPosition(nil, @ARect);
  2692.             end;
  2693.         end;
  2694.     end;
  2695.  
  2696.   end;
  2697.  
  2698.   procedure TVideoWindow.ConstrainedResize(var MinWidth, MinHeight, MaxWidth, MaxHeight: Integer);
  2699.   begin
  2700.     inherited ConstrainedResize(MinWidth, MinHeight, MaxWidth, MaxHeight);
  2701.     Resize;
  2702.   end;
  2703.  
  2704.   function TVideoWindow.GetVideoHandle: THandle;
  2705.   begin
  2706.     if FVideoWindow <> nil then
  2707.       result := FindWindowEx(Parent.Handle,0,Pchar('VideoRenderer'), Pchar(name))
  2708.     else
  2709.       Result := Canvas.Handle;
  2710.   end;
  2711.  
  2712.   class function TVideoWindow.CheckVMR: boolean;
  2713.   var
  2714.     AFilter: IBaseFilter;
  2715.     CW: Word;
  2716.   begin
  2717.     CW := Get8087CW;
  2718.     try
  2719.     result := (CoCreateInstance(CLSID_VideoMixingRenderer9, nil, CLSCTX_INPROC, IID_IBaseFilter ,AFilter) = S_OK);
  2720.     finally
  2721.       Set8087CW(CW);
  2722.       AFilter := nil;
  2723.     end;
  2724.   end;
  2725.  
  2726.   procedure TVideoWindow.SetFullScreen(Value: boolean);
  2727.   var
  2728.     StyleEX: LongWord;
  2729.   begin
  2730.     if FVideoWindow <> nil then
  2731.       case Value of
  2732.         true:
  2733.           begin
  2734.             CheckDSError(FVideoWindow.put_Owner(0));
  2735.             CheckDSError(FVideoWindow.put_WindowStyle(FWindowStyle and not(WS_BORDER or WS_CAPTION or WS_THICKFRAME)));
  2736.             StyleEX := FWindowStyleEx and not(WS_EX_CLIENTEDGE or WS_EX_STATICEDGE
  2737.               or WS_EX_WINDOWEDGE or WS_EX_DLGMODALFRAME);
  2738.             if FTopMost then StyleEX := StyleEX or WS_EX_TOPMOST;
  2739.             CheckDSError(FVideoWindow.put_WindowStyleEx(StyleEX));
  2740.             CheckDSError(FVideoWindow.SetWindowPosition(0,0,screen.Width,screen.Height));
  2741.             FIsFullScreen := true;
  2742.           end;
  2743.         false:
  2744.           begin
  2745.             CheckDSError(FVideoWindow.put_Owner(Parent.Handle));
  2746.             CheckDSError(FVideoWindow.put_WindowStyle(FWindowStyle or WS_CHILD or WS_CLIPSIBLINGS));
  2747.             CheckDSError(FVideoWindow.put_WindowStyleEx(FWindowStyleEx));
  2748.             CheckDSError(FVideoWindow.SetWindowPosition(self.Left,self.Top,self.Width,self.Height));
  2749.             FIsFullScreen := false;
  2750.           end;
  2751.       end;
  2752.  
  2753.     if FWindowLess <> nil then
  2754.       FIsFullScreen := false;
  2755.  
  2756.     FFullScreen := Value;
  2757.   end;
  2758.  
  2759.  
  2760.   function TVideoWindow.QueryInterface(const IID: TGUID; out Obj): HResult;
  2761.   begin
  2762.     if IsEqualGUID(IID_IVMRWindowlessControl9, IID) and (FWindowLess <> nil) then
  2763.     begin
  2764.       result := S_OK;
  2765.       IunKnown(Obj) := FWindowLess;
  2766.       exit;
  2767.     end;
  2768.     result := inherited QueryInterface(IID, Obj);
  2769.     if failed(result) and assigned(FBaseFilter) then
  2770.       result := FBaseFilter.QueryInterface(IID, Obj);
  2771.   end;
  2772.  
  2773.   procedure TVideoWindow.GraphEvent(Event, Param1, Param2: integer);
  2774.   begin
  2775.     case Event of
  2776.       EC_PALETTE_CHANGED:
  2777.         if FVideoWindow <> nil then
  2778.           begin
  2779.             SetFullScreen(FFullScreen);
  2780.             CheckDSError(FVideoWindow.put_Caption(name));
  2781.             CheckDSError(FVideoWindow.put_MessageDrain(Handle));
  2782.           end;
  2783.       EC_VMR_RENDERDEVICE_SET:
  2784.         begin
  2785.           if (FVMROptions.FMode = vmrWindowed) then
  2786.           begin
  2787.             CheckDSError(FVideoWindow.put_Caption(name));
  2788.             CheckDSError(FVideoWindow.put_MessageDrain(Handle));
  2789.           end;
  2790.         end;
  2791.     end;
  2792.   end;
  2793.  
  2794.   function TVideoWindow.CheckInputPinsConnected: boolean;
  2795.   var
  2796.     PinList: TPinList;
  2797.     i: Integer;
  2798.   begin
  2799.     result := False;
  2800.     if (FBaseFilter = nil) then Exit;
  2801.     PinList := TPinList.Create(FBaseFilter);
  2802.     try
  2803.       for i := 0 to PinList.Count - 1 do
  2804.         if PinList.Connected[i] then
  2805.         begin
  2806.           Result := True;
  2807.           Break;
  2808.         end;
  2809.     finally
  2810.       PinList.Free;
  2811.     end;
  2812.   end;
  2813.  
  2814.  
  2815.  procedure TVideoWindow.ControlEvent(Event: TControlEvent; Param: integer = 0);
  2816.  var
  2817.    FilterInfo: TFilterInfo;
  2818.    FilterList: TFilterList;
  2819.    i: integer;
  2820.    GUID: TGUID;
  2821.  begin
  2822.    case Event of
  2823.       ceDVDRendered: // mean our Video Filter have been removed
  2824.         begin
  2825.           ZeroMemory(@FilterInfo, SizeOf(TFilterInfo));
  2826.           CheckDSError(FBaseFilter.QueryFilterInfo(FilterInfo));
  2827.           if not assigned(FilterInfo.pGraph) then
  2828.           begin
  2829.             FilterList:= TFilterList.Create(FilterGraph.FFilterGraph);
  2830.             if FilterList.Count > 0 then
  2831.               for i := 0 to FilterList.Count - 1 do
  2832.               begin
  2833.                 FilterList.Items[i].GetClassID(GUID);
  2834.                 if ISEqualGUID(GUID, CLSID_VideoRenderer) and (Mode = vmNormal) then
  2835.                   begin
  2836.                     FBaseFilter  := nil;
  2837.                     FVideoWindow := nil;
  2838.                     FWindowLess  := nil;
  2839.                     FBaseFilter := FilterList.Items[i];
  2840.                     FBaseFilter.QueryInterface(IVideoWindow, FVideoWindow);
  2841.                     break;
  2842.                   end;
  2843.               end;
  2844.           end;
  2845.         end;
  2846.       cePlay:
  2847.         case FMode of
  2848.           vmNormal:
  2849.             if FVideoWindow <> nil then
  2850.               begin
  2851.                 SetFullScreen(FFullScreen);
  2852.                 CheckDSError(FVideoWindow.put_Caption(name));
  2853.                 CheckDSError(FVideoWindow.put_MessageDrain(Handle));
  2854.               end;
  2855.           vmVMR: SetFullScreen(FFullScreen);
  2856.         end;
  2857.  
  2858.    end;
  2859.  end;
  2860.  
  2861.   procedure TVideoWindow.WndProc(var Message: TMessage);
  2862.   begin
  2863.     if ((Message.Msg = WM_CONTEXTMENU) and FullScreen) then
  2864.       begin
  2865.         if assigned(PopupMenu) then
  2866.           if PopupMenu.AutoPopup then
  2867.           begin
  2868.             PopupMenu.Popup(mouse.CursorPos.X, mouse.CursorPos.Y);
  2869.             Message.Result := 1;
  2870.           end;
  2871.       end
  2872.     else
  2873.       inherited WndProc(Message);
  2874.   end;
  2875.  
  2876.   procedure TVideoWindow.SetTopMost(TopMost: boolean);
  2877.   begin
  2878.     FTopMost := TopMost;
  2879.     if FFullScreen then SetFullScreen(true);
  2880.   end;
  2881.  
  2882.   procedure TVideoWindow.MouseDown(Button: TMouseButton;
  2883.     Shift: TShiftState; X, Y: Integer);
  2884.   begin
  2885.     if FIsFullScreen then
  2886.       inherited MouseDown(Button, Shift, mouse.CursorPos.X, mouse.CursorPos.Y)
  2887.     else
  2888.       inherited MouseDown(Button, Shift, X, Y)
  2889.   end;
  2890.  
  2891.   procedure TVideoWindow.MouseMove(Shift: TShiftState; X, Y: Integer);
  2892.   begin
  2893.     if Fisfullscreen then
  2894.       inherited MouseMove(Shift, mouse.CursorPos.X, mouse.CursorPos.Y)
  2895.     else
  2896.       inherited MouseMove(Shift, X, Y)
  2897.   end;
  2898.  
  2899.   procedure TVideoWindow.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  2900.   begin
  2901.     if Fisfullscreen then
  2902.       inherited MouseUp(Button, Shift, mouse.CursorPos.X, mouse.CursorPos.Y)
  2903.     else
  2904.       inherited MouseUp(Button, Shift, X, Y)
  2905.   end;
  2906.  
  2907.   function TVideoWindow.VMRGetBitMap(Stream: TStream): boolean;
  2908.   var
  2909.     Image: PBitmapInfoHeader;
  2910.     BFH: TBITMAPFILEHEADER;
  2911.     function DibSize: cardinal; begin result := (Image.biSize + Image.biSizeImage + Image.biClrUsed * sizeof(TRGBQUAD)); end;
  2912.     function DibNumColors: cardinal;
  2913.     begin if (image.biClrUsed = 0) and (image.biBitCount <= 8) then
  2914.           result := 1 shl integer(image.biBitCount) else
  2915.           result := image.biClrUsed; end;
  2916.     function DibPaletteSize: cardinal; begin result := (DibNumColors * sizeof(TRGBQUAD)) end;
  2917.   begin
  2918.     assert(assigned(Stream));
  2919.     result := false;
  2920.     if FWindowLess <> nil then
  2921.     if Succeeded(FWindowLess.GetCurrentImage(PByte(image))) then
  2922.     begin
  2923.       BFH.bfType      := $4d42; // BM
  2924.       BFH.bfSize      := DibSize + sizeof(TBITMAPFILEHEADER);
  2925.       BFH.bfReserved1 := 0;
  2926.       BFH.bfReserved2 := 0;
  2927.       BFH.bfOffBits   := sizeof(TBITMAPFILEHEADER) + image.biSize + DibPaletteSize;
  2928.       Stream.Write(BFH, SizeOf(TBITMAPFILEHEADER));
  2929.       Stream.Write(image^, BFH.bfSize);
  2930.       Stream.Position :=0;
  2931.       CoTaskMemFree(image);
  2932.       result := true;
  2933.     end;
  2934.   end;
  2935.  
  2936.   function TVideoWindow.GetVisible: boolean;
  2937.   begin
  2938.     result := inherited visible;
  2939.   end;
  2940.  
  2941.   procedure TVideoWindow.SetVisible(Vis: boolean);
  2942.   begin
  2943.     inherited Visible := Vis;
  2944.     if assigned(FVideoWindow) then CheckDSError(FVideoWindow.put_Visible(vis));
  2945.   end;
  2946.  
  2947.   procedure TVideoWindow.SetAllocator(Allocator: TAbstractAllocatorClass; UserID: Cardinal);
  2948.   begin
  2949.     FAllocatorClass := Allocator;
  2950.     FRenderLessUserID := UserID;
  2951.   end;
  2952.  
  2953. // *****************************************************************************
  2954. //  TSampleGrabber
  2955. // *****************************************************************************
  2956.  
  2957.   procedure TSampleGrabber.SetFilterGraph(AFilterGraph: TFilterGraph);
  2958.   begin
  2959.     if AFilterGraph = FFilterGraph then exit;
  2960.     if FFilterGraph <> nil then FFilterGraph.RemoveFilter(self);
  2961.     if AFilterGraph <> nil then AFilterGraph.InsertFilter(self);
  2962.     FFilterGraph := AFilterGraph;
  2963.   end;
  2964.  
  2965.   function TSampleGrabber.GetFilter: IBaseFilter;
  2966.   begin
  2967.     result := FBaseFilter;
  2968.   end;
  2969.  
  2970.   function TSampleGrabber.GetName: string;
  2971.   begin
  2972.     result := name;
  2973.   end;
  2974.  
  2975.   procedure TSampleGrabber.NotifyFilter(operation: TFilterOperation; Param: integer = 0);
  2976.   var
  2977.     EnumPins: IEnumPins;
  2978.   begin
  2979.     case operation of
  2980.       foAdding    : Cocreateinstance(CLSID_SampleGrabber, nil, CLSCTX_INPROC ,IID_IBASEFilter, FBaseFilter);
  2981.       foAdded     :
  2982.          begin
  2983.            FBaseFilter.QueryInterface(IID_ISampleGrabber,SampleGrabber);
  2984.            FBaseFilter.EnumPins(EnumPins);
  2985.            EnumPins.Next(1,InPutPin,nil);
  2986.            EnumPins.Next(1,OutPutPin,nil);
  2987.            EnumPins := nil;
  2988.            UpdateMediaType;
  2989.            SampleGrabber.SetBufferSamples(true);
  2990.            if assigned(FOnBuffer) then
  2991.              SampleGrabber.SetCallback(Self ,1);
  2992.          end;
  2993.       foRemoving  :
  2994.         begin
  2995.           FBaseFilter.Stop;
  2996.           InPutPin.Disconnect;
  2997.           OutPutPin.Disconnect;
  2998.         end;
  2999.       foRemoved   :
  3000.         begin
  3001.           SampleGrabber.SetCallback(nil ,1);
  3002.           SampleGrabber.SetBufferSamples(false);
  3003.           FBaseFilter   := nil;
  3004.           SampleGrabber := nil;
  3005.           InPutPin      := nil;
  3006.           OutPutPin     := nil;
  3007.         end;
  3008.       foRefresh: UpdateMediaType;
  3009.     end;
  3010.   end;
  3011.  
  3012.   constructor TSampleGrabber.Create(AOwner: TComponent);
  3013.   begin
  3014.     inherited Create(AOwner);
  3015.     FCriticalSection := TCriticalSection.Create;
  3016.     assert(CheckFilter, 'The SampleGrabber Filter is not available on this system.');
  3017.     FMediaType := TMediaType.Create(MEDIATYPE_Video);
  3018.     FMediaType.SubType := MEDIASUBTYPE_RGB24;
  3019.     FMediaType.FormatType := FORMAT_VideoInfo;
  3020.     new(BMPInfo);
  3021.   end;
  3022.  
  3023.   destructor TSampleGrabber.Destroy;
  3024.   begin
  3025.     FilterGraph := nil;
  3026.     FMediaType.Free;
  3027.     Dispose(BMPInfo);
  3028.     FCriticalSection.Free;
  3029.     inherited destroy;
  3030.   end;
  3031.  
  3032.   class function TSampleGrabber.CheckFilter: boolean;
  3033.   var
  3034.     AFilter: IBaseFilter;
  3035.   begin
  3036.     result := Cocreateinstance(CLSID_SampleGrabber, nil, CLSCTX_INPROC ,IID_IBASEFilter, AFilter) = S_OK;
  3037.     AFilter := nil;
  3038.   end;
  3039.  
  3040.   procedure TSampleGrabber.Notification(AComponent: TComponent; Operation: TOperation);
  3041.   begin
  3042.     inherited Notification(AComponent, Operation);
  3043.     if ((AComponent = FFilterGraph) and (Operation = opRemove)) then
  3044.         FFilterGraph := nil;
  3045.   end;
  3046.  
  3047.   procedure TSampleGrabber.UpdateMediaType;
  3048.   begin
  3049.     if assigned(SampleGrabber) then
  3050.     begin
  3051.       FBaseFilter.Stop;
  3052.       InPutPin.Disconnect;
  3053.       SampleGrabber.SetMediaType(MediaType.AMMediaType^);
  3054.     end;
  3055.   end;
  3056.  
  3057.   procedure TSampleGrabber.SetBMPCompatible(Source: PAMMediaType; SetDefault: cardinal);
  3058.   var
  3059.     SubType : TGUID;
  3060.     BitCount: LongWord;
  3061.   begin
  3062.     BitCount := SetDefault;
  3063.       MediaType.ResetFormatBuffer;
  3064.       ZeroMemory(MediaType.AMMediaType, sizeof(TAMMediaType));
  3065.       MediaType.majortype := MEDIATYPE_Video;
  3066.       MediaType.formattype := FORMAT_VideoInfo;
  3067.       if Source = nil then
  3068.       begin
  3069.         case SetDefault of
  3070.           0      : MediaType.subtype := MEDIASUBTYPE_RGB24;
  3071.           1      : MediaType.subtype := MEDIASUBTYPE_RGB1;
  3072.           2 ..4  : MediaType.subtype := MEDIASUBTYPE_RGB4;
  3073.           5 ..8  : MediaType.subtype := MEDIASUBTYPE_RGB8;
  3074.           9 ..16 : MediaType.subtype := MEDIASUBTYPE_RGB555;
  3075.           17..24 : MediaType.subtype := MEDIASUBTYPE_RGB24;
  3076.           25..32 : MediaType.subtype := MEDIASUBTYPE_RGB32
  3077.         else
  3078.           MediaType.subtype := MEDIASUBTYPE_RGB32;
  3079.         end;
  3080.         UpdateMediaType;
  3081.         exit;
  3082.       end;
  3083.  
  3084.       SubType := Source.subtype;
  3085.       if (IsEqualGUID(SubType, MEDIASUBTYPE_RGB1)   or
  3086.           IsEqualGUID(SubType, MEDIASUBTYPE_RGB4)   or
  3087.           IsEqualGUID(SubType, MEDIASUBTYPE_RGB8)   or
  3088.           IsEqualGUID(SubType, MEDIASUBTYPE_RGB555) or
  3089.           IsEqualGUID(SubType, MEDIASUBTYPE_RGB24)  or
  3090.           IsEqualGUID(SubType, MEDIASUBTYPE_RGB32)) then
  3091.             MediaType.subtype := SubType // no change
  3092.       else
  3093.       begin
  3094.         // get bitcount
  3095.         if assigned(Source.pbFormat) then
  3096.         if IsEqualGUID(Source.formattype, FORMAT_VideoInfo) then
  3097.           BitCount := PVideoInfoHeader(Source.pbFormat)^.bmiHeader.biBitCount    else
  3098.         if IsEqualGUID(Source.formattype, FORMAT_VideoInfo2) then
  3099.           BitCount := PVideoInfoHeader2(Source.pbFormat)^.bmiHeader.biBitCount   else
  3100.         if IsEqualGUID(Source.formattype, FORMAT_MPEGVideo) then
  3101.           BitCount := PMPEG1VideoInfo(Source.pbFormat)^.hdr.bmiHeader.biBitCount else
  3102.         if IsEqualGUID(Source.formattype, FORMAT_MPEG2Video) then
  3103.           BitCount := PMPEG2VideoInfo(Source.pbFormat)^.hdr.bmiHeader.biBitCount;
  3104.         case BitCount of
  3105.           0      : MediaType.subtype := MEDIASUBTYPE_RGB24;
  3106.           1      : MediaType.subtype := MEDIASUBTYPE_RGB1;
  3107.           2 ..4  : MediaType.subtype := MEDIASUBTYPE_RGB4;
  3108.           5 ..8  : MediaType.subtype := MEDIASUBTYPE_RGB8;
  3109.           9 ..16 : MediaType.subtype := MEDIASUBTYPE_RGB555;
  3110.           17..24 : MediaType.subtype := MEDIASUBTYPE_RGB24;
  3111.           25..32 : MediaType.subtype := MEDIASUBTYPE_RGB32
  3112.         else
  3113.           MediaType.subtype := MEDIASUBTYPE_RGB32;
  3114.         end;
  3115.       end;
  3116.       UpdateMediaType;
  3117.   end;
  3118.  
  3119.   function TSampleGrabber.GetBitmap(Bitmap: TBitmap; Buffer: Pointer; BufferLen: Integer): boolean;
  3120.   var
  3121.     hr         : HRESULT;
  3122.     BMIHeader  : TBitmapInfoHeader;
  3123.     AMediaType : TAMMediaType;
  3124.     buf        : pointer;
  3125.   begin
  3126.     result := false;
  3127.     if ((Buffer = nil) or (BufferLen = 0)) then exit;
  3128.     if not assigned(Bitmap) then exit;
  3129.     hr := SampleGrabber.GetConnectedMediaType(AMediaType);
  3130.     if (hr <> S_OK) then exit;
  3131.     if IsEqualGUID(AMediaType.majortype, MEDIATYPE_Video) then
  3132.     begin
  3133.       case Amediatype.formattype.D1 of
  3134.         $05589F80: BMIHeader := PVideoInfoHeader(Amediatype.pbFormat)^.bmiHeader;
  3135.         $F72A76A0: BMIHeader := PVideoInfoHeader2(Amediatype.pbFormat)^.bmiHeader;
  3136.       end;
  3137.       FillChar(BMPInfo^, 44, 0);
  3138.       Move(bmiHeader, BMPInfo.bmiHeader, 40);
  3139.       bitmap.Handle := CreateDIBSection(0, BMPInfo^, DIB_RGB_COLORS, buf, 0, 0);
  3140.       if buf = nil then exit;
  3141.       Move(buffer^, buf^, BufferLen);
  3142.       result := true;
  3143.     end;
  3144.     FreeMediaType(@AMediaType);
  3145.   end;
  3146.  
  3147.   function TSampleGrabber.GetBitmap(Bitmap: TBitmap): boolean;
  3148.   var
  3149.     hr         : HRESULT;
  3150.     BMIHeader  : TBitmapInfoHeader;
  3151.     BufferSize : longint;
  3152.     AMediaType : TAMMediaType;
  3153.     buffer     : pointer;
  3154.   begin
  3155.     result := false;
  3156.     if not assigned(Bitmap) then exit;
  3157.     if not assigned(SampleGrabber) then exit;
  3158.     hr := SampleGrabber.GetConnectedMediaType(AMediaType);
  3159.     if (hr <> S_OK) then exit;
  3160.     if IsEqualGUID(AMediaType.majortype, MEDIATYPE_Video) then
  3161.     begin
  3162.       case Amediatype.formattype.D1 of
  3163.         $05589F80: BMIHeader := PVideoInfoHeader(Amediatype.pbFormat)^.bmiHeader;
  3164.         $F72A76A0: BMIHeader := PVideoInfoHeader2(Amediatype.pbFormat)^.bmiHeader;
  3165.       end;
  3166.       ZeroMemory(BMPInfo, sizeof(TBitmapInfo));
  3167.       CopyMemory(@BMPInfo.bmiHeader, @bmiHeader, sizeof(TBITMAPINFOHEADER));
  3168.       bitmap.Handle := CreateDIBSection(0, BMPInfo^, DIB_RGB_COLORS, buffer, 0, 0);
  3169.       HR := SampleGrabber.GetCurrentBuffer(BufferSize, buffer);
  3170.       if (hr <> S_OK) then exit;
  3171.       result := true;
  3172.     end;
  3173.     FreeMediaType(@AMediaType);
  3174.   end;
  3175.  
  3176.   function TSampleGrabber.QueryInterface(const IID: TGUID; out Obj): HResult;
  3177.   begin
  3178.     result := inherited QueryInterface(IID, Obj);
  3179.     if failed(result) and assigned(FBaseFilter) then
  3180.       result := FBaseFilter.QueryInterface(IID, Obj);
  3181.   end;
  3182.  
  3183.   function TSampleGrabber.BufferCB(SampleTime: Double; pBuffer: PByte;
  3184.     BufferLen: Integer): HResult;
  3185.   begin
  3186.     if assigned(FOnBuffer) then
  3187.     begin
  3188.       FCriticalSection.Enter;
  3189.       try
  3190.         FOnBuffer(self, SampleTime, pBuffer, BufferLen);
  3191.       finally
  3192.         FCriticalSection.Leave;
  3193.       end;
  3194.     end;
  3195.     result := S_OK;
  3196.   end;
  3197.  
  3198.   function TSampleGrabber.SampleCB(SampleTime: Double;
  3199.     pSample: IMediaSample): HResult;
  3200.   begin
  3201.     result := S_OK;
  3202.   end;
  3203.   
  3204. // *****************************************************************************
  3205. //  TFilter
  3206. // *****************************************************************************
  3207.  
  3208.   function TFilter.GetFilter: IBaseFilter;
  3209.   begin
  3210.     result := FFilter;
  3211.   end;
  3212.  
  3213.   function TFilter.GetName: string;
  3214.   begin
  3215.     result := name;
  3216.   end;
  3217.  
  3218.   procedure TFilter.NotifyFilter(operation: TFilterOperation; Param: integer = 0);
  3219.   begin
  3220.     case operation of
  3221.       foAdding: FFilter := BaseFilter.CreateFilter;
  3222.       foRemoving: if FFilter <> nil then FFilter.Stop;
  3223.       foRemoved: FFilter := nil;
  3224.       foRefresh: if assigned(FFilterGraph) then
  3225.                    begin
  3226.                      FFilterGraph.RemoveFilter(self);
  3227.                      FFilterGraph.InsertFilter(self);
  3228.                    end;
  3229.     end;
  3230.   end;
  3231.  
  3232.   constructor TFilter.Create(AOwner: TComponent); 
  3233.   begin
  3234.     inherited Create(AOwner);
  3235.     FBaseFilter := TBaseFilter.Create;
  3236.   end;
  3237.  
  3238.   destructor TFilter.Destroy;
  3239.   begin
  3240.     FBaseFilter.Free;
  3241.     FilterGraph := nil;
  3242.     inherited Destroy;
  3243.   end;
  3244.  
  3245.   procedure TFilter.SetFilterGraph(AFilterGraph: TFilterGraph);
  3246.   begin
  3247.     if AFilterGraph = FFilterGraph then exit;
  3248.     if FFilterGraph <> nil then FFilterGraph.RemoveFilter(self);
  3249.     if AFilterGraph <> nil then AFilterGraph.InsertFilter(self);
  3250.     FFilterGraph := AFilterGraph;
  3251.   end;
  3252.  
  3253.   procedure TFilter.Notification(AComponent: TComponent; Operation: TOperation);
  3254.   begin
  3255.     inherited Notification(AComponent, Operation);
  3256.     if ((AComponent = FFilterGraph) and (Operation = opRemove)) then
  3257.         FFilterGraph := nil;
  3258.   end;
  3259.  
  3260.   function TFilter.QueryInterface(const IID: TGUID; out Obj): HResult; 
  3261.   begin
  3262.     result := inherited QueryInterface(IID, Obj);
  3263.     if not Succeeded(Result) then
  3264.       if Assigned(FFilter) then
  3265.         result := FFilter.QueryInterface(IID, Obj);
  3266.   end;
  3267.  
  3268. // *****************************************************************************
  3269. //  TASFWriter
  3270. // *****************************************************************************
  3271.  
  3272.   constructor TASFWriter.Create(AOwner: TComponent);
  3273.   begin
  3274.     inherited Create(AOwner);
  3275.     FAutoIndex := true;
  3276.     FMultiPass := False;
  3277.     FDontCompress := False;
  3278.   end;
  3279.  
  3280.   destructor TASFWriter.Destroy;
  3281.   begin
  3282.     FilterGraph := nil;
  3283.     inherited Destroy;
  3284.   end;
  3285.  
  3286.   procedure TASFWriter.SetFilterGraph(AFilterGraph: TFilterGraph);
  3287.   begin
  3288.     if AFilterGraph = FFilterGraph then exit;
  3289.     if FFilterGraph <> nil then FFilterGraph.RemoveFilter(self);
  3290.     if AFilterGraph <> nil then AFilterGraph.InsertFilter(self);
  3291.     FFilterGraph := AFilterGraph;
  3292.   end;
  3293.  
  3294.   function TASFWriter.GetFilter: IBaseFilter;
  3295.   begin
  3296.     result := FFilter;
  3297.   end;
  3298.  
  3299.   function TASFWriter.GetName: string;
  3300.   begin
  3301.     result := name;
  3302.   end;
  3303.  
  3304.   procedure TASFWriter.NotifyFilter(operation: TFilterOperation; Param: integer = 0);
  3305.   var
  3306.     PinList: TPinList;
  3307.     ServiceProvider: IServiceProvider;
  3308.     FAsfConfig: IConfigAsfWriter2;
  3309.   begin
  3310.     case operation of
  3311.       foAdding: cocreateinstance(CLSID_WMAsfWriter, nil, CLSCTX_INPROC ,IBaseFilter, FFilter);
  3312.       foAdded : begin
  3313.                   if assigned(FFilter) then
  3314.                   begin
  3315.                     SetProfile(FProfile);
  3316.                     SetFileName(FFileName);
  3317.                     if Succeeded(FFilter.QueryInterface(IID_IConfigAsfWriter2, FAsfConfig)) then
  3318.                     begin
  3319.                       FAsfConfig.SetParam(AM_CONFIGASFWRITER_PARAM_AUTOINDEX, Cardinal(FAutoIndex), 0);
  3320.                       FAsfConfig.SetParam(AM_CONFIGASFWRITER_PARAM_MULTIPASS, Cardinal(FMultiPass), 0);
  3321.                       FAsfConfig.SetParam(AM_CONFIGASFWRITER_PARAM_DONTCOMPRESS, Cardinal(FDontCompress), 0);
  3322.                     end;
  3323.  
  3324.                     PinList:= TPinList.Create(FFilter);
  3325.                     try
  3326.                       if PinList.Count >= 1 then
  3327.                       begin
  3328.                         AudioInput := PinList.Items[0];
  3329.                         if PinList.Count = 2 then
  3330.                         begin
  3331.                           VideoInput := PinList.Items[1];
  3332.                           VideoInput.QueryInterface(IID_IAMStreamConfig, VideoStreamConfig);
  3333.                         end;
  3334.                         AudioInput.QueryInterface(IID_IAMStreamConfig, AudioStreamConfig);
  3335.                         if Succeeded(QueryInterface(IServiceProvider, ServiceProvider)) then
  3336.                         begin
  3337.                           ServiceProvider.QueryService(IID_IWMWriterAdvanced2, IID_IWMWriterAdvanced2, WriterAdvanced2);
  3338.                           ServiceProvider := nil;
  3339.                         end;
  3340.                         if ((FPort > 0) and (FMaxUsers > 0)) then
  3341.                         if Succeeded(WMCreateWriterNetworkSink(WriterNetworkSink)) then
  3342.                         begin
  3343.                           WriterNetworkSink.SetNetworkProtocol(WMT_PROTOCOL_HTTP);
  3344.                           WriterNetworkSink.SetMaximumClients(FMaxUsers);
  3345.                           WriterNetworkSink.Open(FPort);
  3346.                           WriterAdvanced2.AddSink(WriterNetworkSink);
  3347.                         end;
  3348.                       end;
  3349.                     finally
  3350.                       PinList.Free;
  3351.                     end;
  3352.  
  3353.                   end;
  3354.                 end;
  3355.       foRemoving: begin
  3356.                     if assigned(FFilter) then FFilter.Stop;
  3357.                     if assigned(WriterNetworkSink) then
  3358.                     begin
  3359.                       WriterNetworkSink.Disconnect;
  3360.                       WriterNetworkSink.Close;
  3361.                     end;
  3362.                     if assigned(AudioInput) then AudioInput.Disconnect;
  3363.                     if assigned(VideoInput) then VideoInput.Disconnect;
  3364.                   end;
  3365.  
  3366.       foRemoved: begin
  3367.                    WriterAdvanced2      := nil;
  3368.                    WriterNetworkSink    := nil;
  3369.                    AudioInput           := nil;
  3370.                    VideoInput           := nil;
  3371.                    AudioStreamConfig    := nil;
  3372.                    VideoStreamConfig    := nil;
  3373.                    FFilter              := nil;
  3374.                  end;
  3375.     end;
  3376.   end;
  3377.  
  3378.   procedure TASFWriter.Notification(AComponent: TComponent; Operation: TOperation);
  3379.   begin
  3380.     inherited Notification(AComponent, Operation);
  3381.     if ((AComponent = FFilterGraph) and (Operation = opRemove)) then
  3382.         FFilterGraph := nil;
  3383.   end;
  3384.  
  3385.   function TASFWriter.GetProfile: TWMPofiles8;
  3386.   var
  3387.     GUIDProf: TGUID;
  3388.     ConfigAsfWriter: IConfigAsfWriter;
  3389.   begin
  3390.     if Succeeded(QueryInterface(IConfigAsfWriter, ConfigAsfWriter)) then
  3391.     begin
  3392.       ConfigAsfWriter.GetCurrentProfileGuid(GUIDProf);
  3393.       result := ProfileFromGUID(GUIDProf);
  3394.       ConfigAsfWriter := nil;
  3395.     end
  3396.     else
  3397.       result := FProfile
  3398.   end;
  3399.  
  3400.   procedure TASFWriter.SetProfile(profile: TWMPofiles8);
  3401.   var
  3402.     ConfigAsfWriter: IConfigAsfWriter;
  3403.   begin
  3404.     if Succeeded(QueryInterface(IConfigAsfWriter, ConfigAsfWriter)) then
  3405.     begin
  3406.       ConfigAsfWriter.ConfigureFilterUsingProfileGuid(WMProfiles8[profile]);
  3407.       ConfigAsfWriter := nil;
  3408.     end
  3409.     else
  3410.       FProfile := profile;
  3411.   end;
  3412.  
  3413.   function TASFWriter.GetFileName: String;
  3414.   var
  3415.     F: PWideChar;
  3416.     FileSinkFilter2: IFileSinkFilter2;
  3417.   begin
  3418.     if Succeeded(QueryInterface(IFileSinkFilter2, FileSinkFilter2)) then
  3419.     begin
  3420.       FileSinkFilter2.GetCurFile(F,nil);
  3421.       FileSinkFilter2 := nil;
  3422.       result := F;
  3423.     end
  3424.     else
  3425.       result := FFileName;
  3426.   end;
  3427.  
  3428.   procedure TASFWriter.SetFileName(FileName: String);
  3429.   var FileSinkFilter2: IFileSinkFilter2;
  3430.   begin
  3431.     FFileName := FileName;
  3432.     if Succeeded(QueryInterface(IFileSinkFilter2, FileSinkFilter2)) then
  3433.     begin
  3434.       FileSinkFilter2.SetFileName(PWideChar(FFileName),nil);
  3435.       FileSinkFilter2 := nil;
  3436.     end;
  3437.   end;
  3438.  
  3439.   function TASFWriter.QueryInterface(const IID: TGUID; out Obj): HResult;
  3440.   begin
  3441.     result := inherited QueryInterface(IID, Obj);
  3442.     if failed(result) and assigned(FFilter) then
  3443.       result := FFilter.QueryInterface(IID, Obj);
  3444.   end;
  3445.  
  3446. // *****************************************************************************
  3447. //  TDSTrackBar
  3448. // *****************************************************************************
  3449.  
  3450.   procedure TDSTrackBar.SetFilterGraph(AFilterGraph: TFilterGraph);
  3451.   begin
  3452.     if AFilterGraph = FFilterGraph then exit;
  3453.     if FFilterGraph <> nil then FFilterGraph.RemoveEventNotifier(self);
  3454.     if AFilterGraph <> nil then AFilterGraph.InsertEventNotifier(self);
  3455.     FFilterGraph := AFilterGraph;
  3456.   end;
  3457.  
  3458.   constructor TDSTrackBar.Create(AOwner: TComponent);
  3459.   begin
  3460.     inherited Create(AOwner);
  3461.     FMouseDown    := false;
  3462.     FEnabled      := false;
  3463.     FInterval     := 1000;
  3464.     FWindowHandle := AllocateHWnd(TimerWndProc);
  3465.   end;
  3466.  
  3467.   destructor TDSTrackBar.Destroy;
  3468.   begin
  3469.     FEnabled := False;
  3470.     UpdateTimer;
  3471.     FilterGraph := nil;
  3472.     DeallocateHWnd(FWindowHandle);
  3473.     FMediaSeeking := nil;
  3474.     inherited Destroy;
  3475.   end;
  3476.  
  3477.   procedure TDSTrackBar.Notification(AComponent: TComponent;
  3478.     Operation: TOperation);
  3479.   begin
  3480.     inherited Notification(AComponent, Operation);
  3481.     if ((AComponent = FFilterGraph) and (Operation = opRemove)) then
  3482.       begin
  3483.         FMediaSeeking := nil;
  3484.         FFilterGraph  := nil;
  3485.       end;
  3486.   end;
  3487.  
  3488.   procedure TDSTrackBar.GraphEvent(Event, Param1, Param2: integer);
  3489.   var
  3490.     Duration: int64;
  3491.     Zero: int64;
  3492.   begin
  3493.     case Event of
  3494.       EC_CLOCK_CHANGED: if assigned(FMediaSeeking) then
  3495.         begin
  3496.           Zero := 0;
  3497.           FMediaSeeking.GetDuration(Duration);
  3498.           FMediaSeeking.SetPositions(Zero, AM_SEEKING_AbsolutePositioning,
  3499.                                      Duration   , AM_SEEKING_NoPositioning);
  3500.         end;
  3501.      end;
  3502.   end;
  3503.  
  3504.   procedure TDSTrackBar.ControlEvent(Event: TControlEvent; Param: integer = 0);
  3505.   begin
  3506.     case event of
  3507.       cePlay: TimerEnabled := Enabled;
  3508.       cePause..ceStop: TimerEnabled := false;
  3509.       ceActive: case Param of
  3510.                   0: FMediaSeeking := nil;
  3511.                   1: FFilterGraph.QueryInterface(IMediaSeeking, FMediaSeeking);
  3512.                 end;
  3513.     end;
  3514.   end;
  3515.  
  3516.   procedure TDSTrackBar.SetTimerEnabled(Value: Boolean);
  3517.   begin
  3518.     if Value <> FEnabled then
  3519.     begin
  3520.       FEnabled := Value;
  3521.       UpdateTimer;
  3522.     end;
  3523.   end;
  3524.  
  3525.   procedure TDSTrackBar.SetInterval(Value: Cardinal);
  3526.   begin
  3527.     if Value <> FInterval then
  3528.     begin
  3529.       FInterval := Value;
  3530.       UpdateTimer;
  3531.     end;
  3532.   end;
  3533.  
  3534.   procedure TDSTrackBar.SetOnTimer(Value: TTimerEvent);
  3535.   begin
  3536.     FOnTimer := Value;
  3537.     UpdateTimer;
  3538.   end;
  3539.  
  3540.   procedure TDSTrackBar.UpdateTimer;
  3541.   begin
  3542.     KillTimer(FWindowHandle, 1);
  3543.     if (FInterval <> 0) and FEnabled then
  3544.       if SetTimer(FWindowHandle, 1, FInterval, nil) = 0 then
  3545.         raise EOutOfResources.Create(SNoTimers);
  3546.   end;
  3547.  
  3548.   procedure TDSTrackBar.Timer;
  3549.   var
  3550.     CurrentPos, StopPos: int64;
  3551.     MlsCurrentPos, MlsStopPos: Cardinal;
  3552.   begin
  3553.     if assigned(FMediaSeeking) and (not FMouseDown) then
  3554.       if Succeeded(FMediaSeeking.GetDuration(StopPos)) then
  3555.       if Succeeded(FMediaSeeking.GetCurrentPosition(CurrentPos)) then
  3556.       begin
  3557.         MlsCurrentPos := RefTimeToMiliSec(CurrentPos);
  3558.         MlsStopPos    := RefTimeToMiliSec(StopPos);
  3559.         min := 0;
  3560.         max := MlsStopPos div TimerInterval;
  3561.         Position := MlsCurrentPos div TimerInterval;
  3562.         if Assigned(FOnTimer) then FOnTimer(Self, MlsCurrentPos, MlsStopPos);
  3563.       end;
  3564.   end;
  3565.  
  3566.   procedure TDSTrackBar.TimerWndProc(var Msg: TMessage);
  3567.   begin
  3568.     with Msg do
  3569.       if Msg = WM_TIMER then
  3570.         try
  3571.           Timer;
  3572.         except
  3573.           Application.HandleException(Self);
  3574.         end
  3575.       else
  3576.         Result := DefWindowProc(FWindowHandle, Msg, wParam, lParam);
  3577.   end;
  3578.  
  3579.   procedure TDSTrackBar.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  3580.   var
  3581.     StopPosition, CurrentPosition: int64;
  3582.   begin
  3583.     inherited MouseUp(Button, Shift, X, Y);
  3584.     if Button = mbLeft then
  3585.      if assigned(FMediaSeeking) then
  3586.        begin
  3587.          FMediaSeeking.GetStopPosition(StopPosition);
  3588.          CurrentPosition := (StopPosition * Position) div max ;
  3589.          FMediaSeeking.SetPositions(CurrentPosition, AM_SEEKING_AbsolutePositioning,
  3590.                                     StopPosition   , AM_SEEKING_NoPositioning);
  3591.  
  3592.        end;
  3593.     FMouseDown := False;
  3594.   end;
  3595.  
  3596.   procedure TDSTrackBar.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  3597.   begin
  3598.     inherited MouseDown(Button, Shift, X, Y);
  3599.     if Button = mbLeft then FMouseDown := true;
  3600.   end;
  3601.  
  3602.   // --------------------------- Color Control -------------------------------
  3603.   constructor TColorControl.Create(AOwner: TDSVideoWindowEx2);
  3604.   begin
  3605.     inherited Create;
  3606.     FOwner := AOwner;
  3607.     ZeroMemory(@FDefault,SizeOf(TDDColorControl));
  3608.     with FDefault do
  3609.     begin
  3610.       dwSize := SizeOf(TDDCOLORCONTROL);
  3611.       dwFlags := DDCOLOR_BRIGHTNESS or DDCOLOR_CONTRAST or DDCOLOR_HUE
  3612.                  or DDCOLOR_SATURATION or DDCOLOR_GAMMA or DDCOLOR_SHARPNESS
  3613.                  or DDCOLOR_COLORENABLE;
  3614.       lBrightness := 750;
  3615.       lContrast := 10000;
  3616.       lGamma := 1;
  3617.       lHue := 0;
  3618.       lSaturation := 10000;
  3619.       lSharpness := 5;
  3620.       lColorEnable := integer(True);
  3621.       dwReserved1 := 0;
  3622.     end;
  3623.     FBrightness := FDefault.lBrightness;
  3624.     FContrast := FDefault.lContrast;
  3625.     FGamma := FDefault.lGamma;
  3626.     FHue := FDefault.lHue;
  3627.     FSaturation := FDefault.lSaturation;
  3628.     FSharpness := FDefault.lSharpness;
  3629.     FUtilColor := Bool(FDefault.lColorEnable);
  3630.   end;
  3631.  
  3632.   procedure TColorControl.ReadDefault;
  3633.   var
  3634.     EnumPins   : IEnumPins;
  3635.     Pin        : IPin;
  3636.     ul         : cardinal;
  3637.     pd         : TPinDirection;
  3638.     MPC        : IMixerPinConfig2;
  3639.     Tel        : Integer;
  3640.     FG         : IFilterGraph;
  3641.     FilterList : TFilterList;
  3642.     Hr         : HResult;
  3643.     OVM        : IBaseFilter;
  3644.     FClass     : TGuid;
  3645.     Tmp        : TDDColorControl;
  3646.   begin
  3647.     if (csDesigning in TDSVideoWindowEx2(FOwner).ComponentState) or
  3648.        (TDSVideoWindowEx2(FOwner).FFilterGraph = nil) or
  3649.        (TDSVideoWindowEx2(FOwner).FFilterGraph.Active = False) then Exit;
  3650.  
  3651.     MPC := nil;
  3652.     OVM := nil;
  3653.     FG  := nil;
  3654.     FG := TDSVideoWindowEx2(FOwner).FFilterGraph.FFilterGraph;
  3655.     FilterList := TFilterList.Create(FG);
  3656.     try
  3657.       for Tel := 0 to FilterList.Count -1 do
  3658.       begin
  3659.         FilterList[Tel].GetClassID(FClass);
  3660.         if IsEqualGuid(FClass, CLSID_OverlayMixer) then
  3661.           OVM := FilterList[Tel];
  3662.         if IsEqualGuid(FClass, CLSID_OverlayMixer2) then
  3663.           OVM := FilterList[Tel];
  3664.       end;
  3665.  
  3666.       if OVM = nil then Exit;
  3667.       Hr := OVM.EnumPins(EnumPins);
  3668.       if Failed(Hr) then Exit;
  3669.  
  3670.       Tel := 0;
  3671.       while (EnumPins.Next(1, Pin, @ul) = S_OK) and (ul = 1) and (Tel = 0) do
  3672.       begin
  3673.         Hr := Pin.QueryDirection(pd);
  3674.         if Failed(Hr) then Exit;
  3675.  
  3676.         if pd = PINDIR_INPUT then
  3677.         begin
  3678.           Hr := Pin.QueryInterface(IID_IMixerPinConfig2, MPC);
  3679.           if Failed(Hr) then Exit;
  3680.           Inc(Tel);
  3681.         end;
  3682.         Pin := nil;
  3683.       end;
  3684.       EnumPins := nil;
  3685.  
  3686.       ZeroMemory(@Tmp,SizeOf(TDDColorControl));
  3687.       Tmp.dwSize:=SizeOf(TDDCOLORCONTROL);
  3688.  
  3689.       Hr := MPC.GetOverlaySurfaceColorControls(Tmp);
  3690.       if Failed(Hr) then Exit;
  3691.  
  3692.       FDefault := Tmp;
  3693.     finally
  3694.       FilterList.Free;
  3695.       FG         := nil;
  3696.       OVM        := nil;
  3697.       EnumPins  := nil;
  3698.       Pin       := nil;
  3699.       MPC       := nil;
  3700.     end;
  3701.   end;
  3702.  
  3703.   procedure TColorControl.UpdateColorControls;
  3704.   var
  3705.     EnumPins   : IEnumPins;
  3706.     Pin        : IPin;
  3707.     ul         : cardinal;
  3708.     pd         : TPinDirection;
  3709.     MPC        : IMixerPinConfig2;
  3710.     Tel        : Integer;
  3711.     FG         : IFilterGraph;
  3712.     FilterList : TFilterList;
  3713.     Hr         : HResult;
  3714.     OVM        : IBaseFilter;
  3715.     FClass     : TGuid;
  3716.     Tmp        : TDDColorControl;
  3717.   begin
  3718.     if (csDesigning in TDSVideoWindowEx2(FOwner).ComponentState) or
  3719.        (TDSVideoWindowEx2(FOwner).FFilterGraph = nil) or
  3720.        (TDSVideoWindowEx2(FOwner).FFilterGraph.Active = False) then Exit;
  3721.  
  3722.     MPC := nil;
  3723.     OVM  := nil;
  3724.     FG   := nil;
  3725.     FG := TDSVideoWindowEx2(FOwner).FFilterGraph.FFilterGraph;
  3726.     FilterList := TFilterList.Create(FG);
  3727.     try
  3728.       for Tel := 0 to FilterList.Count -1 do
  3729.       begin
  3730.         FilterList[Tel].GetClassID(FClass);
  3731.         if IsEqualGuid(FClass, CLSID_OverlayMixer) then
  3732.           OVM := FilterList[Tel];
  3733.         if IsEqualGuid(FClass, CLSID_OverlayMixer2) then
  3734.           OVM := FilterList[Tel];
  3735.       end;
  3736.  
  3737.       if OVM = nil then Exit;
  3738.       Hr := OVM.EnumPins(EnumPins);
  3739.       if Failed(Hr) then Exit;
  3740.  
  3741.       Tel := 0;
  3742.       while (EnumPins.Next(1, Pin, @ul) = S_OK) and (ul = 1) and (Tel = 0) do
  3743.       begin
  3744.         Hr := Pin.QueryDirection(pd);
  3745.         if Failed(Hr) then Exit;
  3746.  
  3747.         if pd = PINDIR_INPUT then
  3748.         begin
  3749.           Hr := Pin.QueryInterface(IID_IMixerPinConfig2, MPC);
  3750.           if Failed(Hr) then Exit;
  3751.           Inc(Tel);
  3752.         end;
  3753.         Pin := nil;
  3754.       end;
  3755.       EnumPins := nil;
  3756.  
  3757.       Tmp.dwSize := SizeOf(TDDCOLORCONTROL);
  3758.       Tmp.dwFlags := DDCOLOR_BRIGHTNESS or DDCOLOR_CONTRAST or DDCOLOR_HUE or DDCOLOR_SATURATION or DDCOLOR_GAMMA or DDCOLOR_SHARPNESS or DDCOLOR_COLORENABLE;
  3759.       Tmp.lBrightness := FBrightness;
  3760.       Tmp.lContrast := FContrast;
  3761.       Tmp.lHue := FHue;
  3762.       Tmp.lSaturation := FSaturation;
  3763.       Tmp.lSharpness := FSharpness;
  3764.       Tmp.lGamma := FGamma;
  3765.       Tmp.lColorEnable := integer(FUtilColor);
  3766.       Tmp.dwReserved1 := 0;
  3767.  
  3768.       Hr := MPC.setOverlaySurfaceColorControls(Pointer(@Tmp));
  3769.       if Failed(Hr) then Exit;
  3770.     finally
  3771.       FilterList.Free;
  3772.       FG         := nil;
  3773.       OVM        := nil;
  3774.       EnumPins  := nil;
  3775.       Pin       := nil;
  3776.       MPC       := nil;
  3777.     end;
  3778.   end;
  3779.  
  3780.   procedure TColorControl.GetColorControls;
  3781.   var
  3782.     EnumPins   : IEnumPins;
  3783.     Pin        : IPin;
  3784.     ul         : cardinal;
  3785.     pd         : TPinDirection;
  3786.     MPC        : IMixerPinConfig2;
  3787.     Tel        : Integer;
  3788.     FG         : IFilterGraph;
  3789.     FilterList : TFilterList;
  3790.     Hr         : HResult;
  3791.     OVM        : IBaseFilter;
  3792.     FClass     : TGuid;
  3793.     Tmp        : TDDColorControl;
  3794.   begin
  3795.     if (csDesigning in TDSVideoWindowEx2(FOwner).ComponentState) or
  3796.        (TDSVideoWindowEx2(FOwner).FFilterGraph = nil) or
  3797.        (TDSVideoWindowEx2(FOwner).FFilterGraph.Active = False) then Exit;
  3798.  
  3799.     MPC := nil;
  3800.     OVM := nil;
  3801.     FG  := nil;
  3802.     FG := TDSVideoWindowEx2(FOwner).FFilterGraph.FFilterGraph;
  3803.     FilterList := TFilterList.Create(FG);
  3804.     try
  3805.       for Tel := 0 to FilterList.Count -1 do
  3806.       begin
  3807.         FilterList[Tel].GetClassID(FClass);
  3808.         if IsEqualGuid(FClass, CLSID_OverlayMixer) then
  3809.           OVM := FilterList[Tel];
  3810.         if IsEqualGuid(FClass, CLSID_OverlayMixer2) then
  3811.           OVM := FilterList[Tel];
  3812.       end;
  3813.  
  3814.       if OVM = nil then Exit;
  3815.       Hr := OVM.EnumPins(EnumPins);
  3816.       if Failed(Hr) then Exit;
  3817.  
  3818.       Tel := 0;
  3819.       while (EnumPins.Next(1, Pin, @ul) = S_OK) and (ul = 1) and (Tel = 0) do
  3820.       begin
  3821.         Hr := Pin.QueryDirection(pd);
  3822.         if Failed(Hr) then Exit;
  3823.  
  3824.         if pd = PINDIR_INPUT then
  3825.         begin
  3826.           Hr := Pin.QueryInterface(IID_IMixerPinConfig2, MPC);
  3827.           if Failed(Hr) then Exit;
  3828.           Inc(Tel);
  3829.         end;
  3830.         Pin := nil;
  3831.       end;
  3832.       EnumPins := nil;
  3833.  
  3834.       ZeroMemory(@Tmp,SizeOf(TDDColorControl));
  3835.       Tmp.dwSize := SizeOf(TDDCOLORCONTROL);
  3836.  
  3837.       Hr := MPC.GetOverlaySurfaceColorControls(Tmp);
  3838.       if Failed(Hr) then
  3839.       begin
  3840.         FBrightness := 750;
  3841.         FContrast := 10000;
  3842.         FHue := 0;
  3843.         FSaturation := 10000;
  3844.         FSharpness := 5;
  3845.         FGamma := 1;
  3846.         FUtilColor := True;
  3847.         Exit;
  3848.       end
  3849.       else
  3850.       begin
  3851.         FBrightness := Tmp.lBrightness;
  3852.         FContrast := Tmp.lContrast;
  3853.         FHue := Tmp.lHue;
  3854.         FSaturation := Tmp.lSaturation;
  3855.         FSharpness := Tmp.lSharpness;
  3856.         FGamma := Tmp.lGamma;
  3857.         FUtilColor := Bool(Tmp.lColorEnable);
  3858.       end;
  3859.     finally
  3860.       FilterList.Free;
  3861.       FG        := nil;
  3862.       OVM       := nil;
  3863.       EnumPins  := nil;
  3864.       Pin       := nil;
  3865.       MPC       := nil;
  3866.     end;
  3867.   end;
  3868.  
  3869.   procedure TColorControl.RestoreDefault;
  3870.   begin
  3871.     FBrightness := FDefault.lBrightness;
  3872.     FContrast := FDefault.lContrast;
  3873.     FHue := FDefault.lHue;
  3874.     FSaturation := FDefault.lSaturation;
  3875.     FSharpness := FDefault.lSharpness;
  3876.     FGamma := FDefault.lGamma;
  3877.     FUtilColor := Bool(FDefault.lColorEnable);
  3878.     if (not (csDesigning in TDSVideoWindowEx2(FOwner).ComponentState)) and
  3879.        (TDSVideoWindowEx2(FOwner).FFilterGraph <> nil) and
  3880.        (TDSVideoWindowEx2(FOwner).FFilterGraph.Active = True) then
  3881.          UpdateColorControls;
  3882.   end;
  3883.  
  3884.   Procedure TColorControl.SetBrightness(Value : Integer);
  3885.   begin
  3886.     if (Value > -1) and (Value < 10001) then
  3887.     begin
  3888.       if Value <> FBrightness then
  3889.         FBrightness := Value;
  3890.       if (not (csDesigning in TDSVideoWindowEx2(FOwner).ComponentState)) and
  3891.          (TDSVideoWindowEx2(FOwner).FFilterGraph <> nil) and
  3892.          (TDSVideoWindowEx2(FOwner).FFilterGraph.Active = True) then
  3893.            UpdateColorControls;
  3894.     end
  3895.     else
  3896.       raise Exception.CreateFmt('Value %d out of range. Value must bee between 0 -> 10.000', [Value]);
  3897.   end;
  3898.  
  3899.   Procedure TColorControl.SetContrast(Value : Integer);
  3900.   begin
  3901.     if (Value > -1) and (Value < 20001) then
  3902.     begin
  3903.       if Value <> FContrast then
  3904.         FContrast := Value;
  3905.       if (not (csDesigning in TDSVideoWindowEx2(FOwner).ComponentState)) and
  3906.          (TDSVideoWindowEx2(FOwner).FFilterGraph <> nil) and
  3907.          (TDSVideoWindowEx2(FOwner).FFilterGraph.Active = True) then
  3908.            UpdateColorControls;
  3909.     end
  3910.     else
  3911.       raise Exception.CreateFmt('Value %d out of range. Value must bee between 0 -> 20.000', [Value]);
  3912.   end;
  3913.  
  3914.   procedure TColorControl.SetHue(Value : Integer);
  3915.   begin
  3916.     if (Value > -181) and (Value < 182) then
  3917.     begin
  3918.       if Value <> FHue then
  3919.         FHue := Value;
  3920.       if (not (csDesigning in TDSVideoWindowEx2(FOwner).ComponentState)) and
  3921.          (TDSVideoWindowEx2(FOwner).FFilterGraph <> nil) and
  3922.          (TDSVideoWindowEx2(FOwner).FFilterGraph.Active = True) then
  3923.            UpdateColorControls;
  3924.     end
  3925.     else
  3926.       raise Exception.CreateFmt('Value %d out of range. Value must bee between -180 -> 180', [Value]);
  3927.   end;
  3928.  
  3929.   procedure TColorControl.SetSaturation(Value : Integer);
  3930.   begin
  3931.     if (Value > -1) and (Value < 20001) then
  3932.     begin
  3933.       if Value <> FSaturation then
  3934.         FSaturation := Value;
  3935.       if (not (csDesigning in TDSVideoWindowEx2(FOwner).ComponentState)) and
  3936.          (TDSVideoWindowEx2(FOwner).FFilterGraph <> nil) and
  3937.          (TDSVideoWindowEx2(FOwner).FFilterGraph.Active = True) then
  3938.            UpdateColorControls;
  3939.     end
  3940.     else
  3941.       raise Exception.CreateFmt('Value %d out of range. Value must bee between 0 -> 20.000', [Value]);
  3942.   end;
  3943.  
  3944.   procedure TColorControl.SetSharpness(Value : Integer);
  3945.   begin
  3946.     if (Value > -1) and (Value < 11) then
  3947.     begin
  3948.       if Value <> FSharpness then
  3949.         FSharpness := Value;
  3950.       if (not (csDesigning in TDSVideoWindowEx2(FOwner).ComponentState)) and
  3951.          (TDSVideoWindowEx2(FOwner).FFilterGraph <> nil) and
  3952.          (TDSVideoWindowEx2(FOwner).FFilterGraph.Active = True) then
  3953.            UpdateColorControls;
  3954.     end
  3955.     else
  3956.       raise Exception.CreateFmt('Value %d out of range. Value must bee between 0 -> 10', [Value]);
  3957.   end;
  3958.  
  3959.   procedure TColorControl.SetGamma(Value : Integer);
  3960.   begin
  3961.     if (Value > 0) and (Value < 501) then
  3962.     begin
  3963.       if Value <> FGamma then
  3964.         FGamma := Value;
  3965.       if (not (csDesigning in TDSVideoWindowEx2(FOwner).ComponentState)) and
  3966.          (TDSVideoWindowEx2(FOwner).FFilterGraph <> nil) and
  3967.          (TDSVideoWindowEx2(FOwner).FFilterGraph.Active = True) then
  3968.            UpdateColorControls;
  3969.     end
  3970.     else
  3971.       raise Exception.CreateFmt('Value %d out of range. Value must bee between 1 -> 500', [Value]);
  3972.   end;
  3973.  
  3974.   procedure TColorControl.SetUtilColor(Value : Boolean);
  3975.   begin
  3976.     FUtilColor := Value;
  3977.     if (not (csDesigning in TDSVideoWindowEx2(FOwner).ComponentState)) and
  3978.        (TDSVideoWindowEx2(FOwner).FFilterGraph <> nil) and
  3979.        (TDSVideoWindowEx2(FOwner).FFilterGraph.Active = True) then
  3980.          UpdateColorControls;
  3981.   end;
  3982.  
  3983.   function TColorControl.GetBrightness : Integer;
  3984.   begin
  3985.     if (not (csDesigning in TDSVideoWindowEx2(FOwner).ComponentState)) and
  3986.        (TDSVideoWindowEx2(FOwner).FFilterGraph <> nil) and
  3987.        (TDSVideoWindowEx2(FOwner).FFilterGraph.Active = True) then
  3988.          GetColorControls;
  3989.     Result := fBrightness;
  3990.   end;
  3991.  
  3992.   function TColorControl.GetContrast : Integer;
  3993.   begin
  3994.     if (not (csDesigning in TDSVideoWindowEx2(FOwner).ComponentState)) and
  3995.        (TDSVideoWindowEx2(FOwner).FFilterGraph <> nil) and
  3996.        (TDSVideoWindowEx2(FOwner).FFilterGraph.Active = True) then
  3997.          GetColorControls;
  3998.     Result := fContrast;
  3999.   end;
  4000.  
  4001.   function TColorControl.GetHue : Integer;
  4002.   begin
  4003.     if (not (csDesigning in TDSVideoWindowEx2(FOwner).ComponentState)) and
  4004.        (TDSVideoWindowEx2(FOwner).FFilterGraph <> nil) and
  4005.        (TDSVideoWindowEx2(FOwner).FFilterGraph.Active = True) then
  4006.          GetColorControls;
  4007.     Result := fHue;
  4008.   end;
  4009.  
  4010.   function TColorControl.GetSaturation : Integer;
  4011.   begin
  4012.     if (not (csDesigning in TDSVideoWindowEx2(FOwner).ComponentState)) and
  4013.        (TDSVideoWindowEx2(FOwner).FFilterGraph <> nil) and
  4014.        (TDSVideoWindowEx2(FOwner).FFilterGraph.Active = True) then
  4015.          GetColorControls;
  4016.     Result := fSaturation;
  4017.   end;
  4018.  
  4019.   function TColorControl.GetSharpness : Integer;
  4020.   begin
  4021.     if (not (csDesigning in TDSVideoWindowEx2(FOwner).ComponentState)) and
  4022.        (TDSVideoWindowEx2(FOwner).FFilterGraph <> nil) and
  4023.        (TDSVideoWindowEx2(FOwner).FFilterGraph.Active = True) then
  4024.          GetColorControls;
  4025.     Result := fSharpness;
  4026.   end;
  4027.  
  4028.   function TColorControl.GetGamma : Integer;
  4029.   begin
  4030.     if (not (csDesigning in TDSVideoWindowEx2(FOwner).ComponentState)) and
  4031.        (TDSVideoWindowEx2(FOwner).FFilterGraph <> nil) and
  4032.        (TDSVideoWindowEx2(FOwner).FFilterGraph.Active = True) then
  4033.          GetColorControls;
  4034.     Result := fGamma;
  4035.   end;
  4036.  
  4037.   function TColorControl.GetUtilColor : Boolean;
  4038.   begin
  4039.     if (not (csDesigning in TDSVideoWindowEx2(FOwner).ComponentState)) and
  4040.        (TDSVideoWindowEx2(FOwner).FFilterGraph <> nil) and
  4041.        (TDSVideoWindowEx2(FOwner).FFilterGraph.Active = True) then
  4042.          GetColorControls;
  4043.     Result := fUtilColor;
  4044.   end;
  4045.  
  4046.   // ---------------------- DSVideoWindowEx2Capabilities -------------------
  4047.  
  4048.   constructor TDSVideoWindowEx2Caps.create(AOwner: TDSVideoWindowEx2);
  4049.   begin
  4050.     inherited Create;
  4051.     Owner := AOwner;
  4052.   end;
  4053.  
  4054.   function TDSVideoWindowEx2Caps.GetCanOverlay : Boolean;
  4055.   begin
  4056.     Result := TDSVideoWindowEx2(Owner).FOverlayMixer <> nil;
  4057.   end;
  4058.  
  4059.   function TDSVideoWindowEx2Caps.GetCanControlBrigtness : Boolean;
  4060.   begin
  4061.     if TDSVideoWindowEx2(Owner).FColorControl <> nil then
  4062.       Result := TDSVideoWindowEx2(Owner).FColorControl.FDefault.dwFlags and DDCOLOR_BRIGHTNESS = DDCOLOR_BRIGHTNESS
  4063.     else
  4064.       Result := False;
  4065.   end;
  4066.  
  4067.   function TDSVideoWindowEx2Caps.GetCanControlContrast : Boolean;
  4068.   begin
  4069.     if TDSVideoWindowEx2(Owner).FColorControl <> nil then
  4070.       Result := TDSVideoWindowEx2(Owner).FColorControl.FDefault.dwFlags and DDCOLOR_CONTRAST = DDCOLOR_CONTRAST
  4071.     else
  4072.       Result := False;
  4073.   end;
  4074.  
  4075.   function TDSVideoWindowEx2Caps.GetCanControlHue : Boolean;
  4076.   begin
  4077.     if TDSVideoWindowEx2(Owner).FColorControl <> nil then
  4078.       Result := TDSVideoWindowEx2(Owner).FColorControl.FDefault.dwFlags and DDCOLOR_HUE = DDCOLOR_HUE
  4079.     else
  4080.       Result := False;
  4081.   end;
  4082.  
  4083.   function TDSVideoWindowEx2Caps.GetCanControlSaturation : Boolean;
  4084.   begin
  4085.     if TDSVideoWindowEx2(Owner).FColorControl <> nil then
  4086.       Result := TDSVideoWindowEx2(Owner).FColorControl.FDefault.dwFlags and DDCOLOR_SATURATION = DDCOLOR_SATURATION
  4087.     else
  4088.       Result := False;
  4089.   end;
  4090.  
  4091.   function TDSVideoWindowEx2Caps.GetCanControlSharpness : Boolean;
  4092.   begin
  4093.     if TDSVideoWindowEx2(Owner).FColorControl <> nil then
  4094.       Result := TDSVideoWindowEx2(Owner).FColorControl.FDefault.dwFlags and DDCOLOR_SHARPNESS = DDCOLOR_SHARPNESS
  4095.     else
  4096.       Result := False;
  4097.   end;
  4098.  
  4099.   function TDSVideoWindowEx2Caps.GetCanControlGamma : Boolean;
  4100.   begin
  4101.     if TDSVideoWindowEx2(Owner).FColorControl <> nil then
  4102.       Result := TDSVideoWindowEx2(Owner).FColorControl.FDefault.dwFlags and DDCOLOR_GAMMA = DDCOLOR_GAMMA
  4103.     else
  4104.       Result := False;
  4105.   end;
  4106.  
  4107.   function TDSVideoWindowEx2Caps.GetCanControlUtilizedColor : Boolean;
  4108.   begin
  4109.     if TDSVideoWindowEx2(Owner).FColorControl <> nil then
  4110.       Result := TDSVideoWindowEx2(Owner).FColorControl.FDefault.dwFlags and DDCOLOR_COLORENABLE = DDCOLOR_COLORENABLE
  4111.     else
  4112.       Result := False;
  4113.   end;
  4114.  
  4115.   // ----------------------------------- Overlay Callback ------------------
  4116.  
  4117.   constructor TOverlayCallBack.Create(Owner : TObject);
  4118.   begin
  4119.     AOwner := Owner;
  4120.   end;
  4121.  
  4122.   function TOverlayCallback.OnUpdateOverlay(bBefore: BOOL; dwFlags: DWORD; bOldVisible: BOOL;
  4123.                var prcOldSrc, prcOldDest: TRECT; bNewVisible: BOOL; var prcNewSrc, prcNewDest: TRECT): HRESULT; stdcall;
  4124.   begin
  4125.     Result := S_OK;
  4126.   end;
  4127.  
  4128.   function TOverlayCallback.OnUpdateColorKey(var pKey: TCOLORKEY; dwColor: DWORD): HRESULT; stdcall;
  4129.   begin
  4130.     TDSVideoWindowEx2(AOwner).FColorKey := pKey.HighColorValue;
  4131.     if Assigned(TDSVideoWindowEx2(AOwner).FOnColorKey) then
  4132.       TDSVideoWindowEx2(AOwner).FOnColorKey(Self);
  4133.     Result := S_OK;
  4134.   end;
  4135.  
  4136.   function TOverlayCallback.OnUpdateSize(dwWidth, dwHeight, dwARWidth, dwARHeight: DWORD): HRESULT; stdcall;
  4137.   begin
  4138.     if (AOwner = nil) then
  4139.     begin
  4140.       Result := S_OK;
  4141.       Exit;
  4142.     end;
  4143.     TDSVideoWindowEx2(AOwner).GetVideoInfo;
  4144.     TDSVideoWindowEx2(AOwner).Clearback;
  4145.     Result := S_OK;
  4146.   end;
  4147.  
  4148.   // ------------------------------ DSVideoWindowEx -------------------------
  4149.  
  4150.   procedure TDSVideoWindowEx2.NotifyFilter(operation: TFilterOperation; Param: integer);
  4151.   var
  4152.     i: integer;
  4153.     EnumPins: TPinList;
  4154.     pGB : IGraphBuilder;
  4155.   begin
  4156.     EnumPins := nil;
  4157.     pGB := nil;
  4158.     try
  4159.       case operation of
  4160.         foAdding:   begin
  4161.                       GraphWasUpdatet  := False;
  4162.                       CoCreateInstance(CLSID_VideoRenderer, nil, CLSCTX_INPROC_SERVER, IID_IBaseFilter ,FBaseFilter);
  4163.                     end;
  4164.         foAdded:    begin
  4165.                       FBaseFilter.QueryInterface(IVideoWindow, FVideoWindow);
  4166.                     end;
  4167.         foRemoving: begin
  4168.                       if FOverlayMixer <> nil then
  4169.                       begin
  4170.                         FColorControl.RestoreDefault;
  4171.                         FBaseFilter.Stop;
  4172.                         EnumPins := TPinList.Create(FOverlayMixer);
  4173.                         if EnumPins.Count > 0 then
  4174.                           for i := 0 to EnumPins.Count - 1 do
  4175.                             EnumPins.Items[i].Disconnect;
  4176.                       end;
  4177.                       if FBaseFilter <> nil then
  4178.                       begin
  4179.                         FBaseFilter.Stop;
  4180.                         EnumPins := TPinList.Create(FBaseFilter);
  4181.                         if EnumPins.Count > 0 then
  4182.                           for i := 0 to EnumPins.Count - 1 do
  4183.                             EnumPins.Items[i].Disconnect;
  4184.                       end;
  4185.                       if FDDXM <> nil then
  4186.                         FDDXM.SetCallbackInterface(nil, 0);
  4187.                       if OverlayCallback <> nil then
  4188.                         OverlayCallback := nil;
  4189.                     end;
  4190.         foRemoved : begin
  4191.                       GraphWasUpdatet  := False;
  4192.                       FDDXM          := nil;
  4193.                       FOverlayMixer    := nil;
  4194.                       FVideoRenderer   := nil;
  4195.                       FVideoWindow     := nil;
  4196.                       FBaseFilter      := nil;
  4197.                     end;
  4198.       end;
  4199.     finally
  4200.       if EnumPins <> nil then
  4201.         EnumPins.Free;
  4202.       pGB := nil;
  4203.     end;
  4204.   end;
  4205.  
  4206.   procedure TDSVideoWindowEx2.GraphEvent(Event, Param1, Param2: integer);
  4207.   begin
  4208.     case Event of
  4209.       EC_PALETTE_CHANGED : RefreshVideoWindow;
  4210.       EC_CLOCK_CHANGED   : begin
  4211.                              if GraphBuildOk then SetVideoZOrder;
  4212.                              SetZoom(FZoom);
  4213.                              SetAspectMode(FAspectMode);
  4214.                              if GraphBuildOk then ClearBack;
  4215.                            end;
  4216.  
  4217.       end;
  4218.   end;
  4219.  
  4220.   function TDSVideoWindowEx2.GetName: string;
  4221.   begin
  4222.     result := name;
  4223.   end;
  4224.  
  4225.  procedure TDSVideoWindowEx2.ControlEvent(Event: TControlEvent; Param: integer = 0);
  4226.  var
  4227.    FilterInfo: TFilterInfo;
  4228.    FilterList: TFilterList;
  4229.    i: integer;
  4230.    GUID: TGUID;
  4231.    TmpName : WideString;
  4232.  begin
  4233.    FilterList := nil;
  4234.    try
  4235.      case Event of
  4236.         ceDVDRendered: begin // mean our Video Filter have been removed
  4237.                          ZeroMemory(@FilterInfo, SizeOf(TFilterInfo));
  4238.                          FBaseFilter.QueryFilterInfo(FilterInfo);
  4239.                          if not assigned(FilterInfo.pGraph) then
  4240.                          begin
  4241.                            FilterList:= TFilterList.Create(FilterGraph.FFilterGraph);
  4242.                            if FilterList.Count > 0 then
  4243.                              for i := 0 to FilterList.Count - 1 do
  4244.                              begin
  4245.                                FilterList.Items[i].GetClassID(GUID);
  4246.                                if ISEqualGUID(GUID, CLSID_VideoRenderer) then
  4247.                                begin
  4248.                                  FOverlayMixer  := nil;
  4249.                                  FBaseFilter    := nil;
  4250.                                  FVideoWindow   := nil;
  4251.                                  FVideoRenderer := nil;
  4252.                                  FBaseFilter := FilterList.Items[i];
  4253.                                  FBaseFilter.QueryInterface(IVideoWindow, FVideoWindow);
  4254.                                  GraphBuildOk := Succeeded(UpdateGraph);
  4255.                                  if GraphBuildOk then
  4256.                                  begin
  4257.                                    FColorControl.ReadDefault; // Read the Colorcontrols settings of the OverlayMixer.
  4258.                                    FColorControl.UpdateColorControls; // Apply our settings to the ColorControls.
  4259.                                  end;
  4260.                                  RefreshVideoWindow;
  4261.                                  break;
  4262.                                end
  4263.                                else
  4264.                                if ISEqualGUID(GUID, CLSID_VideoMixingRenderer) then
  4265.                                begin
  4266.                                  FOverlayMixer  := nil;
  4267.                                  FBaseFilter    := nil;
  4268.                                  FVideoRenderer := nil;
  4269.                                  TmpName := Name;
  4270.                                  if FVideoWindow <> nil then
  4271.                                    FilterGraph.FFilterGraph.AddFilter(FVideoWindow as IBaseFilter, PWideChar(TmpName));
  4272.                                  FBaseFilter := FVideoWindow as IBaseFilter;
  4273.                                  GraphBuildOk := Succeeded(UpdateGraph);
  4274.                                  if GraphBuildOk then
  4275.                                  begin
  4276.                                    FColorControl.ReadDefault; // Read the Colorcontrols settings of the OverlayMixer.
  4277.                                    FColorControl.UpdateColorControls; // Apply our settings to the ColorControls.
  4278.                                  end;
  4279.                                  RefreshVideoWindow;
  4280.                                  break;
  4281.                                end;
  4282.                              end;
  4283.                          end;
  4284.                        end;
  4285.         cePlay:        begin
  4286.                          if not GraphWasUpdatet then
  4287.                          begin
  4288.                            GraphBuildOk := Succeeded(UpdateGraph);
  4289.                            if GraphBuildOk then
  4290.                            begin
  4291.                              FColorControl.ReadDefault; // Read the Colorcontrols settings of the OverlayMixer.
  4292.                              FColorControl.UpdateColorControls; // Apply our settings to the ColorControls.
  4293.                            end;
  4294.                            RefreshVideoWindow;
  4295.                          end;
  4296.                          if GraphBuildOk then
  4297.                          begin
  4298.                            if (not FOverlayVisible) and (not FDesktopPlay) then
  4299.                            begin
  4300.                              FOverlayVisible := True;
  4301.                              if Assigned(FOnOverlay) then
  4302.                                FOnOverlay(Self, True);
  4303.                              Clearback;
  4304.                            end;
  4305.                          end;
  4306.                        end;
  4307.         cePause:       begin
  4308.                          if not GraphWasUpdatet then
  4309.                          begin
  4310.                            GraphBuildOk := Succeeded(UpdateGraph);
  4311.                            if GraphBuildOk then
  4312.                            begin
  4313.                              FColorControl.ReadDefault; // Read the Colorcontrols settings of the OverlayMixer.
  4314.                              FColorControl.UpdateColorControls; // Apply our settings to the ColorControls.
  4315.                            end;
  4316.                            RefreshVideoWindow;
  4317.                          end;
  4318.                          if GraphBuildOk then
  4319.                            if (not FOverlayVisible) and (not FDesktopPlay) then
  4320.                            begin
  4321.                              FOverlayVisible := True;
  4322.                              if Assigned(FOnOverlay) then
  4323.                                FOnOverlay(Self, True);
  4324.                              Clearback;
  4325.                            end;
  4326.                        end;
  4327.         ceStop:        begin
  4328.                          if not GraphWasUpdatet then
  4329.                          begin
  4330.                            GraphBuildOk := Succeeded(UpdateGraph);
  4331.                            if GraphBuildOk then
  4332.                            begin
  4333.                              FColorControl.ReadDefault; // Read the Colorcontrols settings of the OverlayMixer.
  4334.                              FColorControl.UpdateColorControls; // Apply our settings to the ColorControls.
  4335.                            end;
  4336.                            RefreshVideoWindow;
  4337.                          end;
  4338.                          if GraphBuildOk then
  4339.                            if FOverlayVisible then
  4340.                            begin
  4341.                              FOverlayVisible := False;
  4342.                              Clearback;
  4343.                              if Assigned(FOnOverlay) then
  4344.                                FOnOverlay(Self, False);
  4345.                            end;
  4346.                        end;
  4347.        ceFileRendered: begin
  4348.                          GraphBuildOk := Succeeded(UpdateGraph);
  4349.                          if GraphBuildOk then
  4350.                          begin
  4351.                            FColorControl.ReadDefault; // Read the Colorcontrols settings of the OverlayMixer.
  4352.                            FColorControl.UpdateColorControls; // Apply our settings to the ColorControls.
  4353.                          end;
  4354.                          RefreshVideoWindow;
  4355.                        end;
  4356.      end;
  4357.    finally
  4358.      if FilterList <> nil then
  4359.        FilterList.Free;
  4360.    end;
  4361.   end;
  4362.  
  4363.   procedure TDSVideoWindowEx2.RefreshVideoWindow;
  4364.   begin
  4365.     if FVideoWindow <> nil then
  4366.       with FVideoWindow do
  4367.       begin
  4368.         put_Owner(Parent.Handle);
  4369.         put_WindowStyle(FWindowStyle or WS_CHILD or WS_CLIPSIBLINGS);
  4370.         put_WindowStyleEx(FWindowStyleEx);
  4371.         SetWindowPosition(Left, Top, Width, Height);
  4372.         put_Caption(name);
  4373.         put_MessageDrain(Handle);
  4374.         Application.ProcessMessages;
  4375.         put_AutoShow(not FDesktopPlay);
  4376.       end;
  4377.   end;
  4378.  
  4379.   function TDSVideoWindowEx2.GetFilter: IBaseFilter;
  4380.   begin
  4381.     result := FBaseFilter;
  4382.   end;
  4383.  
  4384.   constructor TDSVideoWindowEx2.Create(AOwner: TComponent);
  4385.   begin
  4386.     inherited Create(AOwner);
  4387.     ControlStyle := [csAcceptsControls, csCaptureMouse, csClickEvents,
  4388.     csDoubleClicks, csReflector];
  4389.     TabStop   := true;
  4390.     Height    := 240;
  4391.     Width     := 320;
  4392.     color     := $000000;
  4393.     FColorKey := clNone;
  4394.     FFullScreen := false;
  4395.     FColorControl := TColorControl.create(Self);
  4396.     FCaps := TDSVideoWindowEx2Caps.Create(Self);
  4397.     AspectRatio := rmLetterBox;
  4398.     DigitalZoom := 0;
  4399.     GraphBuildOK := False;
  4400.     FNoScreenSaver := False;
  4401.     FIdleCursor := 0;
  4402.     if (csDesigning in componentstate) then Exit;
  4403.     FFullScreenControl := TForm.Create(nil);
  4404.     FFullScreenControl.Color := Color;
  4405.     FFullScreenControl.DefaultMonitor := dmDesktop;
  4406.     FFullScreenControl.BorderStyle := bsNone;
  4407.     FFullScreenControl.OnCloseQuery := FullScreenCloseQuery;
  4408.     FOldParent := nil;
  4409.     FMonitor := nil;
  4410.     FVideoWindowHandle := 0;
  4411.     GraphWasUpdatet := False;
  4412.     Application.OnIdle := MyIdleHandler;
  4413.   end;
  4414.  
  4415.   destructor TDSVideoWindowEx2.Destroy;
  4416.   begin
  4417.     if DesktopPlayback then
  4418.       NormalPlayback;
  4419.  
  4420.     if FDDXM <> nil then
  4421.       FDDXM.SetCallbackInterface(nil, 0);
  4422.     OverlayCallback := nil;
  4423.     FOverlayMixer   := nil;
  4424.     FFilterGraph    := nil;
  4425.     FVideoWindow    := nil;
  4426.     FVideoRenderer  := nil;
  4427.     FCaps.Free;
  4428.     FColorControl.Free;
  4429.     inherited Destroy;
  4430.   end;
  4431.  
  4432.   procedure TDSVideoWindowEx2.resize;
  4433.   begin
  4434.     if (FVideoWindow <> nil) and (not FFullScreen) and (not DesktopPlayback) then
  4435.       FVideoWindow.SetWindowPosition(Left,Top,Width,Height);
  4436.   end;
  4437.  
  4438.   procedure TDSVideoWindowEx2.Loaded;
  4439.   begin
  4440.     inherited Loaded;
  4441.     FWindowStyle   := GetWindowLong(Handle, GWL_STYLE);
  4442.     FWindowStyleEx := GetWindowLong(Handle, GWL_EXSTYLE);
  4443.   end;
  4444.  
  4445.   procedure TDSVideoWindowEx2.Notification(AComponent: TComponent;
  4446.     Operation: TOperation);
  4447.   begin
  4448.     inherited Notification(AComponent, Operation);
  4449.     if ((AComponent = FFilterGraph) and (Operation = opRemove)) then
  4450.         FFilterGraph := nil;
  4451.   end;
  4452.  
  4453.   procedure TDSVideoWindowEx2.SetFilterGraph(AFilterGraph: TFilterGraph);
  4454.   begin
  4455.     if AFilterGraph = FFilterGraph then exit;
  4456.     if FFilterGraph <> nil then
  4457.     begin
  4458.       FFilterGraph.RemoveFilter(self);
  4459.       FFilterGraph.RemoveEventNotifier(self);
  4460.     end;
  4461.     if AFilterGraph <> nil then
  4462.     begin
  4463.       AFilterGraph.InsertFilter(self);
  4464.       AFilterGraph.InsertEventNotifier(self);
  4465.     end;
  4466.     FFilterGraph := AFilterGraph;
  4467.   end;
  4468.  
  4469.   procedure TDSVideoWindowEx2.SetTopMost(TopMost: boolean);
  4470.   begin
  4471.     FTopMost := TopMost;
  4472.   end;
  4473.  
  4474.   procedure TDSVideoWindowEx2.SetVideoZOrder;
  4475.   var
  4476.     input      : IPin;
  4477.     enum       : IEnumPins;
  4478.     ColorKey   : TColorKey;
  4479.     dwColorKey : DWord;
  4480.     MPC       : IMixerPinConfig;
  4481.   begin
  4482.     if not GraphBuildOK then Exit;
  4483.     try
  4484.       ColorKey.KeyType := CK_INDEX or CK_RGB;
  4485.       ColorKey.PaletteIndex := 0;
  4486.       ColorKey.LowColorValue := $000F000F;
  4487.       ColorKey.HighColorValue := $000F000F;
  4488.  
  4489.       FVideoWindowHandle := findWindowEx(Parent.handle, 0, 'VideoRenderer', pchar(name));
  4490.       if FVideoWindowHandle = 0 then
  4491.         FVideoWindowHandle := findWindowEx(0, 0, 'VideoRenderer', pchar(name));
  4492.       if FVideoWindowHandle = 0 then Exit;
  4493.       SetWindowPos(FVideoWindowHandle, Handle, 0, 0, 0, 0, SWP_SHOWWINDOW or SWP_NOSIZE or SWP_NOMOVE or SWP_NOCOPYBITS or SWP_NOACTIVATE);
  4494.       if (FVideoWindowHandle <> 0) then
  4495.       begin
  4496.         FOverlayMixer.EnumPins(Enum);
  4497.         Enum.Next(1, Input, nil);
  4498.  
  4499.         if Succeeded(Input.QueryInterface(IID_IMixerPinConfig2, MPC)) then
  4500.         begin
  4501.           MPC.GetColorKey(ColorKey, dwColorKey);
  4502.           FColorKey := ColorKey.HighColorValue;
  4503.           if Assigned(FOnColorKey) then
  4504.             FOnColorKey(Self);
  4505.         end;
  4506.       end;
  4507.     finally
  4508.       Input := nil;
  4509.       Enum  := nil;
  4510.       MPC   := nil;
  4511.     end;
  4512.   end;
  4513.  
  4514.   function TDSVideoWindowEx2.QueryInterface(const IID: TGUID; out Obj): HResult;
  4515.   begin
  4516.     result := inherited QueryInterface(IID, Obj);
  4517.     if failed(result) and assigned(FBaseFilter) then
  4518.       result := FBaseFilter.QueryInterface(IID, Obj);
  4519.   end;
  4520.  
  4521.   function TDSVideoWindowEx2.UpdateGraph : HResult;
  4522.   Type
  4523.     TConnectAction = (caConnect, caDisConnect);
  4524.  
  4525.     PConnection = ^TConnection;
  4526.     TConnection = record
  4527.       FromPin : IPin;
  4528.       ToPin   : IPin;
  4529.       Action  : TConnectAction;
  4530.     end;
  4531.  
  4532.   var
  4533.     FilterList    : TFilterList;
  4534.     VMRPinList    : TPinList;
  4535.     OVMPinList    : TPinList;
  4536.     TmpPinList    : TPinList;
  4537.     OrigConnections : TList;
  4538.     TmpVMRPinList : TPinList;
  4539.     Connection : pConnection;
  4540.  
  4541.     i, a: integer;
  4542.     GUID: TGUID;
  4543.     pGB : IGraphBuilder;
  4544.     VRInputPin,
  4545.     VRConnectedToPin : IPin;
  4546.     OVMInputPin      : IPin;
  4547.     OVMOutputPin     : IPIN;
  4548.     Pin              : IPin;
  4549.     pEnumPins        : IEnumPins;
  4550.     ul               : cardinal;
  4551.     pd               : TPinDirection;
  4552.     PinInfo          : TPinInfo;
  4553.     Hr               : HResult;
  4554.     VMR              : IBaseFilter;
  4555.     Line21Dec,
  4556.     Line21Dec2       : IBaseFilter;
  4557.     OVMInConected    : Boolean;
  4558.     OVMOutConected   : Boolean;
  4559.     Found            : Boolean;
  4560.   label
  4561.     FailedSoReconnect, Cleanup, SetDrawExclMode;
  4562.   begin
  4563.     // Check if we are using Overlay.
  4564.     FOverlayMixer := nil;
  4565.     FVideoRenderer := nil;
  4566.     VMR            := nil;
  4567.     Line21Dec      := nil;
  4568.     Line21Dec2     := nil;
  4569.  
  4570.     GraphWasUpdatet := True;
  4571.     OrigConnections := TList.Create;
  4572.     FilterList:= TFilterList.Create(FilterGraph.FFilterGraph);
  4573.     if FilterList.Count > 0 then
  4574.     for i := 0 to FilterList.Count - 1 do
  4575.     begin
  4576.       FilterList.Items[i].GetClassID(GUID);
  4577.       if ISEqualGUID(GUID, CLSID_OverlayMixer) then
  4578.         FOverlayMixer := FilterList.Items[i];
  4579.       if ISEqualGUID(GUID, CLSID_VideoMixingRenderer) then
  4580.         VMR := FilterList.Items[i];
  4581.       if ISEqualGUID(GUID, CLSID_VideoRenderer) then
  4582.         FVideoRenderer := FilterList.Items[i];
  4583.     end;
  4584.  
  4585.     // The Graph holds no overlay mixer filter, Let's add one.
  4586.     Result := FFilterGraph.QueryInterface(IID_IGraphBuilder, pGB);
  4587.     if Failed(Result) then
  4588.     begin
  4589.       Goto Cleanup;
  4590.     end;
  4591.  
  4592.     if FOverlayMixer <> nil then
  4593.     begin
  4594.       // Check if The Overlay Mixer that already exists is connected
  4595.       // correct to out VideoWindow
  4596.       OVMInConected  := False;
  4597.       OVMOutConected := False;
  4598.       OVMPinList := TPinList.Create(FOverlayMixer);
  4599.       for i := 0 To OVMPinList.Count -1 do
  4600.       begin
  4601.         OVMPinList.Items[i].QueryDirection(pd);
  4602.         if pd = PINDIR_OUTPUT then
  4603.         begin
  4604.           if Succeeded(OVMPinlist.Items[i].ConnectedTo(Pin)) then
  4605.           begin
  4606.             Pin.QueryPinInfo(PinInfo);
  4607.             if PinInfo.pFilter = FVideoRenderer then
  4608.               OVMOutConected := True;
  4609.           end;
  4610.         end
  4611.         else
  4612.         begin
  4613.           if Succeeded(OVMPinlist.Items[i].ConnectedTo(Pin)) then
  4614.             OVMInConected := True;
  4615.         end;
  4616.       end;
  4617.       if (not OVMOutConected) or (not OVMInConected) then
  4618.       begin
  4619.         Result := E_FAIL;
  4620.         Goto Cleanup;
  4621.       end
  4622.       else
  4623.       begin
  4624.         // Everything looks okay stop here.
  4625.         OVMPinList.Free;
  4626.         Goto SetDrawExclMode;
  4627.       end;
  4628.     end;
  4629.  
  4630.     Result := CoCreateInstance(CLSID_OverlayMixer, nil, CLSCTX_INPROC, IID_IBaseFilter, FOverlayMixer);
  4631.     if Failed(Result) then goto Cleanup;
  4632.  
  4633.     Result := pGB.AddFilter(fOverlayMixer, 'Overlay Mixer');
  4634.     if Failed(Result) then goto Cleanup;
  4635.  
  4636.     if FVideoRenderer = nil then
  4637.     begin
  4638.       Result := E_Fail;
  4639.       Goto Cleanup;
  4640.     end;
  4641.  
  4642.     Result := FVideoRenderer.EnumPins(pEnumPins);
  4643.     if Failed(Result) then goto Cleanup;
  4644.  
  4645.     Result := pEnumPins.Next(1, VRInputPin, @ul);
  4646.     if Failed(Result) then goto Cleanup;
  4647.  
  4648.     Result := VRInputPin.QueryDirection(pd);
  4649.     if (Failed(Result)) or (PD <> PINDIR_INPUT) then goto Cleanup;
  4650.  
  4651.     if VMR <> nil then
  4652.     begin
  4653.       // The Graph Uses the new VideoMixerRenderer let's try to connect
  4654.       // all filter connected to the VideoMixerRenderer to the Overlay
  4655.       // Mixer filter instead.
  4656.       VMRPinList := TPinList.Create(VMR);
  4657.       OVMPinList := TPinList.Create(FOverlayMixer);
  4658.       TmpVMRPinList := TPinList.Create;
  4659.  
  4660.       I := 0;
  4661.       while (i < VMRPinList.Count) and (Succeeded(VMRPinList.Items[i].ConnectedTo(Pin))) do
  4662.       begin
  4663.         // Let's find the first Input Pin on the overlay mixer not
  4664.         // connected to anything.
  4665.  
  4666.         Result := Pin.Disconnect;
  4667.         if Failed(Result) then goto FailedSoReconnect;
  4668.  
  4669.         Result := VMRPinList.Items[i].Disconnect;
  4670.         if Failed(Result) then goto FailedSoReconnect;
  4671.  
  4672.         New(Connection);
  4673.         Connection^.FromPin := VMRPinList.Items[i];
  4674.         Connection^.ToPin := Pin;
  4675.         Connection^.Action := caDisconnect;
  4676.         OrigConnections.Add(Connection);
  4677.  
  4678.         TmpVMRPinList.Add(Pin);
  4679.         VMRPinList.Update;
  4680.         Inc(i);
  4681.       end;
  4682.  
  4683.       i := 0;
  4684.       Repeat
  4685.         Pin := TmpVMRPinList[i];
  4686.         a := 0;
  4687.         Found := False;
  4688.         Repeat
  4689.           OVMPinList.Items[a].QueryDirection(pd);
  4690.           if pd = PINDIR_INPUT then
  4691.           begin
  4692.             OVMInputPin := OVMPinList.Items[a];
  4693.             if Failed(OVMPinList.Items[a].ConnectedTo(OVMOutputPin)) then
  4694.             begin
  4695.               Found := True;
  4696.             end;
  4697.           end;
  4698.           OVMPinList.Update;
  4699.           inc(a);
  4700.         until (a >= OVMPinList.count) or (Found);
  4701.         if not Found then
  4702.         begin
  4703.           VMRPinList.Free;
  4704.           OVMPinList.Free;
  4705.           Result := E_Fail;
  4706.           goto FailedSoReconnect;
  4707.         end;
  4708.  
  4709.         // Before connecting we need to check if the filter we ar working on is a Line21 Decoder2
  4710.         // And the exchange it with a Line21 Decoder because The Overlay Mixer Filter cannot connect
  4711.         // with a Line21 Decoder2
  4712.         Pin.QueryPinInfo(PinInfo);
  4713.         PinInfo.pFilter.GetClassID(GUID);
  4714.  
  4715.         if ISEqualGUID(GUID, CLSID_Line21Decoder2) then
  4716.         begin
  4717.           Line21Dec2 := PinInfo.pFilter;
  4718.  
  4719.           TmpPinList := TPinList.Create(Line21Dec2);
  4720.           Result := TmpPinList.Items[0].ConnectedTo(Pin);
  4721.           if Failed(Result) then goto FailedSoReconnect;
  4722.  
  4723.           Result := TmpPinList.Items[0].Disconnect;
  4724.           if Failed(Result) then goto FailedSoReconnect;
  4725.  
  4726.           Result := Pin.Disconnect;
  4727.           if Failed(Result) then goto FailedSoReconnect;
  4728.  
  4729.           New(Connection);
  4730.           Connection^.FromPin := Pin;
  4731.           Connection^.ToPin := TmpPinList.Items[0];
  4732.           Connection^.Action := caDisconnect;
  4733.           OrigConnections.Add(Connection);
  4734.           TmpPinList.Free;
  4735.  
  4736.           Result := CoCreateInstance(CLSID_Line21Decoder, nil, CLSCTX_INPROC, IID_IBaseFilter, Line21Dec);
  4737.           if Failed(Result) then goto Cleanup;
  4738.  
  4739.           Result := FilterGraph.FFilterGraph.AddFilter(Line21Dec, 'Line21 Decoder');
  4740.           if Failed(Result) then goto Cleanup;
  4741.  
  4742.           TmpPinList := TPinList.Create(Line21Dec);
  4743.  
  4744.           Result := FilterGraph.FFilterGraph.Connect(Pin, TmpPinList.Items[0]);
  4745.           if Failed(Result) then goto Cleanup;
  4746.  
  4747.           New(Connection);
  4748.           Connection^.FromPin := Pin;
  4749.           Connection^.ToPin := TmpPinList.Items[0];
  4750.           Connection^.Action := caConnect;
  4751.           OrigConnections.Add(Connection);
  4752.  
  4753.           Pin := TmpPinList.Items[1];
  4754.           TmpPinList.Free;
  4755.  
  4756.           Result := pGB.Connect(Pin, OVMInputPin);
  4757.           if Failed(Result) then
  4758.           begin
  4759.             VMRPinList.Free;
  4760.             OVMPinList.Free;
  4761.             Goto Failedsoreconnect;
  4762.           end;
  4763.  
  4764.           New(Connection);
  4765.           Connection^.FromPin := Pin;
  4766.           Connection^.ToPin := OVMInputPin;
  4767.           Connection^.Action := caConnect;
  4768.           OrigConnections.Add(Connection);
  4769.         end
  4770.         else
  4771.         begin
  4772.           Result := pGB.Connect(Pin, OVMInputPin);
  4773.           if Failed(Result) then
  4774.           begin
  4775.             VMRPinList.Free;
  4776.             OVMPinList.Free;
  4777.             Goto Failedsoreconnect;
  4778.           end;
  4779.  
  4780.           New(Connection);
  4781.           Connection^.FromPin := Pin;
  4782.           Connection^.ToPin := OVMInputPin;
  4783.           Connection^.Action := caConnect;
  4784.           OrigConnections.Add(Connection);
  4785.         end;
  4786.  
  4787.         OVMPinList.Update;
  4788.         inc(i);
  4789.       until I >= TmpVMRPinList.Count;
  4790.  
  4791.       VMRPinList.Free;
  4792.       OVMPinList.Free;
  4793.       TmpVMRPinList.Free;
  4794.     end
  4795.     else
  4796.     begin
  4797.       Result := VRInputPin.ConnectedTo(VRConnectedToPin);
  4798.       if Failed(Result) then goto FailedSoReconnect;
  4799.  
  4800.       Result := VRInputPin.Disconnect;
  4801.       if Failed(Result) then goto FailedSoReconnect;
  4802.  
  4803.       Result := VRConnectedToPin.Disconnect;
  4804.       if Failed(Result) then goto FailedSoReconnect;
  4805.  
  4806.       New(Connection);
  4807.       Connection^.FromPin := VRInputPin;
  4808.       Connection^.ToPin := VRConnectedToPin;
  4809.       Connection^.Action := caDisconnect;
  4810.       OrigConnections.Add(Connection);
  4811.  
  4812.       OVMPinList := TPinList.Create(FOverlayMixer);
  4813.       a := 0;
  4814.       Found := False;
  4815.       Repeat
  4816.         OVMPinList.Items[a].QueryDirection(pd);
  4817.         if pd = PINDIR_INPUT then
  4818.         begin
  4819.           OVMInputPin := OVMPinList.Items[a];
  4820.           if Failed(OVMPinList.Items[a].ConnectedTo(Pin)) then
  4821.             Found := True;
  4822.         end;
  4823.         inc(a);
  4824.       until (a >= OVMPinList.count) or (Found);
  4825.       if not Found then
  4826.       begin
  4827.         OVMPinList.Free;
  4828.         Result := E_Fail;
  4829.         Goto Cleanup;
  4830.       end;
  4831.  
  4832.       result := pGB.Connect(VRConnectedToPin, OVMInputPin);
  4833.       if Failed(Result) then
  4834.       begin
  4835.         OVMPinList.Free;
  4836.         Goto FailedSoReconnect;
  4837.       end;
  4838.  
  4839.       New(Connection);
  4840.       Connection^.FromPin := VRConnectedToPin;
  4841.       Connection^.ToPin := OVMInputPin;
  4842.       Connection^.Action := caConnect;
  4843.       OrigConnections.Add(Connection);
  4844.  
  4845.       OVMPinList.Free;
  4846.     end;
  4847.  
  4848.     Result := FOverlayMixer.FindPin('Output', OVMOutputPin);
  4849.     if Failed(Result) then goto FailedSoReconnect;
  4850.  
  4851.     Result := pGB.Connect(OVMOutputPin, VRInputPin);
  4852.     if Failed(Result) then goto FailedSoReconnect;
  4853.  
  4854.     New(Connection);
  4855.     Connection^.FromPin := OVMOutputPin;
  4856.     Connection^.ToPin := VRInputPin;
  4857.     Connection^.Action := caConnect;
  4858.     OrigConnections.Add(Connection);
  4859.  
  4860.   SetDrawExclMode:
  4861.  
  4862.     Result := FOverlayMixer.QueryInterface(IID_IDDrawExclModeVideo, FDDXM);
  4863.     if Failed(Result) then goto FailedSoReconnect;
  4864.  
  4865.     OverlayCallback := TOverlayCallback.Create(Self);
  4866.  
  4867.     Result := FDDXM.SetCallbackInterface(OverlayCallBack, 0);
  4868.     if Failed(Result) then goto FailedSoReconnect;
  4869.  
  4870.     if Line21Dec2 <> nil then
  4871.       filtergraph.FFilterGraph.RemoveFilter(Line21Dec2);
  4872.  
  4873.     if VMR <> nil then
  4874.       filtergraph.FFilterGraph.RemoveFilter(VMR);
  4875.  
  4876.     Goto Cleanup;
  4877.  
  4878.     FailedSoReconnect:
  4879.       for i := OrigConnections.Count -1 downto 0 do
  4880.       begin
  4881.         Connection := OrigConnections[i];
  4882.         Case Connection^.Action of
  4883.           caConnect    : begin
  4884.                            Connection^.FromPin.Disconnect;
  4885.                            Connection^.ToPin.Disconnect;
  4886.                          end;
  4887.           caDisconnect : begin
  4888.                            pGB.Connect(Connection^.FromPin, Connection^.ToPin);
  4889.                          end;
  4890.         end;
  4891.       end;
  4892.  
  4893.       if Line21Dec <> nil then
  4894.         FilterGraph.FFilterGraph.RemoveFilter(Line21Dec);
  4895.  
  4896.       Hr := pGB.RemoveFilter(FOverlayMixer);
  4897.       if Failed(Hr) then
  4898.       begin
  4899.         Result := Hr;
  4900.         Goto CleanUp;
  4901.       end;
  4902.  
  4903.       FOverlayMixer := nil;
  4904.  
  4905.       if VMR <> nil then
  4906.       begin
  4907.         pGB.RemoveFilter((FVideoWindow as IBaseFilter));
  4908.         FVideoWindow := nil;
  4909.         FVideoRenderer := VMR;
  4910.         FVideoWindow := (VMR as IVIdeoWindow);
  4911.       end;
  4912.  
  4913.     Cleanup:
  4914.       for i := 0 to OrigConnections.Count -1 do
  4915.       begin
  4916.         Connection := OrigConnections[i];
  4917.         Connection^.FromPin := nil;
  4918.         Connection^.ToPin := nil;
  4919.       end;
  4920.  
  4921.       VMR := nil;
  4922.       pEnumPins := nil;
  4923.       OVMInputpin := nil;
  4924.       OVMOutputPin := nil;
  4925.       VRInputPin := nil;
  4926.       VRConnectedToPin := nil;
  4927.       Line21Dec := nil;
  4928.       Line21Dec2 := nil;
  4929.       OrigConnections.Free;
  4930.       FilterList.Free;
  4931.   end;
  4932.  
  4933.   procedure TDSVideoWindowEx2.WndProc(var Message: TMessage);
  4934.   begin
  4935.     if (csDesigning in ComponentState) then
  4936.     begin
  4937.       inherited WndProc(Message);
  4938.       Exit;
  4939.     end;
  4940.  
  4941.     if ((Message.Msg = WM_CONTEXTMENU) and FullScreen) then
  4942.       begin
  4943.         if assigned(PopupMenu) then
  4944.           if PopupMenu.AutoPopup then
  4945.           begin
  4946.             PopupMenu.Popup(mouse.CursorPos.X, mouse.CursorPos.Y);
  4947.             Message.Result := 1;
  4948.           end;
  4949.  
  4950.         inherited WndProc(Message);
  4951.         Exit;
  4952.       end;
  4953.  
  4954.     if (Message.Msg = WM_ERASEBKGND) and (GraphBuildOk) then
  4955.     begin
  4956.       Message.Result := -1;
  4957.       Exit;
  4958.     end;
  4959.  
  4960.     if FNoScreenSaver then
  4961.       if (Message.Msg = SC_SCREENSAVE) or (Message.Msg = SC_MONITORPOWER) then
  4962.       begin
  4963.         Message.Result := 0;
  4964.         Exit;
  4965.       end;
  4966.  
  4967.     inherited WndProc(Message);
  4968.   end;
  4969.  
  4970.   procedure TDSVideoWindowEx2.ClearBack;
  4971.   var
  4972.     DC, MemDC: HDC;
  4973.     MemBitmap, OldBitmap: HBITMAP;
  4974.     BackBrush, OverlayBrush : HBrush;
  4975.   begin
  4976.     BackBrush := 0;
  4977.     OverlayBrush := 0;
  4978.     if (csDestroying in componentstate) then exit;
  4979.     DC := GetDC(0);
  4980.     MemBitmap := CreateCompatibleBitmap(DC, ClientRect.Right, ClientRect.Bottom);
  4981.     ReleaseDC(0, DC);
  4982.     MemDC := CreateCompatibleDC(0);
  4983.     OldBitmap := SelectObject(MemDC, MemBitmap);
  4984.     try
  4985.       DC := GetDC(Handle);
  4986.       BackBrush := CreateSolidBrush(Color);
  4987.       FillRect(MemDC, Rect(0,0, ClientRect.Right, ClientRect.Bottom), BackBrush);
  4988.       if not (csDesigning in ComponentState) then
  4989.       begin
  4990.         if Succeeded(GetVideoInfo) and (FOverlayVisible) then
  4991.         begin
  4992.           OverlayBrush := CreateSolidBrush(FColorKey);
  4993.           FillRect(MemDC, FVideoRect, OverlayBrush);
  4994.         end;
  4995.       end;
  4996.       BitBlt(DC, 0, 0, Self.ClientRect.Right, Self.ClientRect.Bottom, MemDC, 0, 0, SRCCOPY);
  4997.     finally
  4998.       SelectObject(MemDC, OldBitmap);
  4999.       DeleteDC(MemDC);
  5000.       DeleteObject(MemBitmap);
  5001.       DeleteObject(BackBrush);
  5002.       DeleteObject(OverlayBrush);
  5003.       ReleaseDC(Handle, DC);
  5004.     end;
  5005.     if Assigned(FOnPaint) then FOnPaint(self);
  5006.   end;
  5007.  
  5008.   procedure TDSVideoWindowEx2.Paint;
  5009.   begin
  5010.     inherited Paint;
  5011.     clearback;
  5012.     if Assigned(FOnPaint) then FOnPaint(self);
  5013.   end;
  5014.  
  5015.   function TDSVideoWindowEx2.GetVideoInfo : HResult;
  5016.   Var
  5017.     BasicVideo : IBasicVideo2;
  5018.     AspX, AspY : DWord;
  5019.     VideoWidth, VideoHeight : DWord;
  5020.   begin
  5021.     Result := E_Fail;
  5022.     if (FVideoWindow = nil) or (FBaseFilter = nil) or (FDDXM = nil) or
  5023.        (FVideoRenderer = nil) or (FOverlayMixer = nil) then Exit;
  5024.  
  5025.     try
  5026.       if FAspectMode = rmLetterbox then
  5027.       begin
  5028.         FDDXM.GetNativeVideoProps(VideoWidth, VideoHeight, AspX, AspY);
  5029.         FVideoRect := StretchRect(ClientRect, Rect(0,0, AspX, AspY));
  5030.       end
  5031.       else
  5032.         FVideoRect := ClientRect;
  5033.       Result := S_OK;
  5034.     finally
  5035.       BasicVideo := nil;
  5036.     end;
  5037.   end;
  5038.  
  5039.   Procedure TDSVideoWindowEx2.StartDesktopPlayback;
  5040.   type
  5041.    TMonitorDefaultTo = (mdNearest, mdNull, mdPrimary);
  5042.   const
  5043.     MonitorDefaultFlags: array[TMonitorDefaultTo] of DWORD = (MONITOR_DEFAULTTONEAREST,
  5044.                                                               MONITOR_DEFAULTTONULL,
  5045.                                                               MONITOR_DEFAULTTOPRIMARY);
  5046.     function FindMonitor(Handle: HMONITOR): TMonitor;
  5047.     var
  5048.       I: Integer;
  5049.     begin
  5050.       Result := nil;
  5051.       for I := 0 to Screen.MonitorCount - 1 do
  5052.       if HMonitor(Screen.Monitors[I].Handle) = HMonitor(Handle) then
  5053.       begin
  5054.         Result := Screen.Monitors[I];
  5055.         break;
  5056.       end;
  5057.     end;
  5058.  
  5059.     function MonitorFromWindow(const Handle: THandle;
  5060.       MonitorDefault: TMonitorDefaultTo = mdNearest): TMonitor;
  5061.     begin
  5062.       Result := FindMonitor(MultiMon.MonitorFromWindow(Handle,
  5063.         MonitorDefaultFlags[MonitorDefault]));
  5064.     end;
  5065.   begin
  5066.     StartDesktopPlayback(MonitorfromWindow(Self.Handle));
  5067.   end;
  5068.  
  5069.   procedure TDSVideoWindowEx2.StartDesktopPlayBack(OnMonitor : TMonitor);
  5070.  
  5071.     procedure SetWallpaper(sWallpaperBMPPath : String);
  5072.     var
  5073.       reg : TRegistry;
  5074.     begin
  5075.       reg := TRegistry.Create;
  5076.       with reg do
  5077.       begin
  5078.         RootKey := HKEY_CURRENT_USER;
  5079.         if KeyExists('\Control Panel\Desktop') then
  5080.           if OpenKey('\Control Panel\Desktop', False) then
  5081.           begin
  5082.             if ValueExists('WallPaper') then
  5083.               WriteString('WallPaper', sWallpaperBMPPath);
  5084.           end;
  5085.       end;
  5086.       reg.Free;
  5087.       SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, nil, SPIF_SENDWININICHANGE );
  5088.     end;
  5089.  
  5090.     function GetWallpaper : String;
  5091.     var
  5092.       reg : TRegistry;
  5093.     begin
  5094.       Result := '';
  5095.       reg := TRegistry.Create;
  5096.       with reg do
  5097.       begin
  5098.         RootKey := HKEY_CURRENT_USER;
  5099.         if KeyExists('\Control Panel\Desktop') then
  5100.           if OpenKey('\Control Panel\Desktop', False) then
  5101.           begin
  5102.             if ValueExists('WallPaper') then
  5103.               Result := ReadString('Wallpaper');
  5104.           end;
  5105.       end;
  5106.       reg.Free;
  5107.     end;
  5108.   var
  5109.     ColorIndex : Integer;
  5110.     Color : Longint;
  5111.   begin
  5112.     if DesktopPlayback then Exit;
  5113.  
  5114.     FMonitor := OnMonitor;
  5115.     OldDesktopPic := GetWallpaper;
  5116.     ColorIndex:=COLOR_DESKTOP;
  5117.     OldDesktopColor := GetSysColor(ColorIndex);
  5118.  
  5119.     SetWallPaper('');
  5120.     Color := ColorTorgb(FColorKey);
  5121.     SetSysColors(1, ColorIndex, Color);
  5122.  
  5123.     if FullScreen then
  5124.       NormalPlayback;
  5125.  
  5126.     FOldParent := Parent;
  5127.  
  5128.     Parent := FFullScreenControl;
  5129.  
  5130.     FFullScreenControl.BoundsRect := rect(OnMonitor.Left,
  5131.                                           OnMonitor.Top,
  5132.                                           OnMonitor.Left + OnMonitor.Width,
  5133.                                           OnMonitor.Top + OnMonitor.Height);
  5134.  
  5135.     FFullScreenControl.Show;
  5136.  
  5137.     FDesktopPlay := True;
  5138.  
  5139.     RefreshVideoWindow;
  5140.     if GraphBuildOk then SetVideoZOrder;
  5141.  
  5142.     FFullScreenControl.Hide;
  5143.     FOverlayVisible := False;
  5144.     ClearBack;
  5145.     if Assigned(FOnOverlay) then
  5146.       FOnOverlay(Self, False);
  5147.   end;
  5148.  
  5149.   procedure TDSVideoWindowEx2.NormalPlayback;
  5150.  
  5151.     procedure SetWallpaper(sWallpaperBMPPath : String);
  5152.     var
  5153.       reg : TRegistry;
  5154.     begin
  5155.       reg := TRegistry.Create;
  5156.       with reg do
  5157.       begin
  5158.         RootKey := HKEY_CURRENT_USER;
  5159.         if KeyExists('\Control Panel\Desktop') then
  5160.           if OpenKey('\Control Panel\Desktop', False) then
  5161.           begin
  5162.             if ValueExists('WallPaper') then
  5163.               WriteString('WallPaper', sWallpaperBMPPath);
  5164.           end;
  5165.       end;
  5166.       reg.Free;
  5167.       SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, nil, SPIF_SENDWININICHANGE );
  5168.     end;
  5169.  
  5170.   var
  5171.     ColorIndex : Integer;
  5172.   begin
  5173.     if DesktopPlayback then
  5174.     begin
  5175.       ColorIndex := COLOR_DESKTOP;
  5176.  
  5177.       SetWallPaper(OldDesktopPic);
  5178.       SetSysColors(1, ColorIndex, OldDesktopColor);
  5179.  
  5180.       FDesktopPlay := False;
  5181.       if (csDestroying in componentstate) then exit;
  5182.     end;
  5183.  
  5184.     if FoldParent <> nil then
  5185.       Parent := FOldParent;
  5186.  
  5187.     if FullScreen then
  5188.     begin
  5189.       FFullScreenControl.Hide;
  5190.       FFullScreenControl.Invalidate;
  5191.       FFullScreen := False;
  5192.     end;
  5193.     RefreshVideoWindow;
  5194.     if GraphBuildOk then SetVideoZOrder;
  5195.     FOverlayVisible := True;
  5196.     ClearBack;
  5197.     if Assigned(FOnOverlay) then
  5198.       FOnOverlay(Self, True);
  5199.     FMonitor := nil;
  5200.   end;
  5201.  
  5202.   procedure TDSVideoWindowEx2.StartFullScreen;
  5203.   type
  5204.    TMonitorDefaultTo = (mdNearest, mdNull, mdPrimary);
  5205.   const
  5206.     MonitorDefaultFlags: array[TMonitorDefaultTo] of DWORD = (MONITOR_DEFAULTTONEAREST,
  5207.                                                               MONITOR_DEFAULTTONULL,
  5208.                                                               MONITOR_DEFAULTTOPRIMARY);
  5209.     function FindMonitor(Handle: HMONITOR): TMonitor;
  5210.     var
  5211.       I: Integer;
  5212.     begin
  5213.       Result := nil;
  5214.       for I := 0 to Screen.MonitorCount - 1 do
  5215.       if HMonitor(Screen.Monitors[I].Handle) = HMonitor(Handle) then
  5216.       begin
  5217.         Result := Screen.Monitors[I];
  5218.         break;
  5219.       end;
  5220.     end;
  5221.  
  5222.     function MonitorFromWindow(const Handle: THandle;
  5223.       MonitorDefault: TMonitorDefaultTo = mdNearest): TMonitor;
  5224.     begin
  5225.       Result := FindMonitor(MultiMon.MonitorFromWindow(Handle,
  5226.         MonitorDefaultFlags[MonitorDefault]));
  5227.     end;
  5228.   begin
  5229.     StartFullScreen(MonitorfromWindow(Self.Handle));
  5230.   end;
  5231.  
  5232.   procedure TDSVideoWindowEx2.StartFullScreen(OnMonitor : TMonitor);
  5233.   begin
  5234.     if FFullscreen then Exit;
  5235.  
  5236.     if DesktopPlayback then
  5237.       NormalPlayback;
  5238.  
  5239.     FMonitor := OnMonitor;
  5240.     FOldParent := Parent;
  5241.  
  5242.     Parent := FFullScreenControl;
  5243.  
  5244.     FFullScreenControl.BoundsRect := rect(OnMonitor.Left,
  5245.                                           OnMonitor.Top,
  5246.                                           OnMonitor.Left + OnMonitor.Width,
  5247.                                           OnMonitor.Top + OnMonitor.Height);
  5248.  
  5249.     if FTopMost then
  5250.       FFullScreenControl.FormStyle := fsStayOnTop
  5251.     Else
  5252.       FFullScreenControl.FormStyle := fsNormal;
  5253.  
  5254.     FFullScreenControl.Show;
  5255.  
  5256.     FFullScreen := True;
  5257.  
  5258.     RefreshVideoWindow;
  5259.     if GraphBuildOk then SetVideoZOrder;
  5260.   end;
  5261.  
  5262.   procedure TDSVideoWindowEx2.FullScreenCloseQuery(Sender: TObject; var CanClose: Boolean);
  5263.   begin
  5264.     if csDestroying in componentstate then
  5265.     begin
  5266.       NormalPlayback;
  5267.       CanClose := True;
  5268.     end
  5269.     else
  5270.       CanClose := False;
  5271.   end;
  5272.  
  5273.   procedure TDSVideoWindowEx2.SetZoom(Value : Integer);
  5274.   var
  5275.     Ratio : Real;
  5276.     TmpX, TmpY : Real;
  5277.     TmpLeft, TmpTop : Real;
  5278.     BasicVideo2 : IBasicVideo2;
  5279.     SLeft, STop, SWidth, SHeight : Integer;
  5280.   begin
  5281.     // Set DigitalZoom
  5282.     if (Value < 0) or (Value > 99) then
  5283.     begin
  5284.       raise Exception.CreateFmt('Value %d out of range. Value must bee between 0 -> 99', [Value]);
  5285.       Exit;
  5286.     end;
  5287.  
  5288.     if (csDesigning in ComponentState) or (FVideoRenderer = nil) then
  5289.     begin
  5290.       FZoom := Value;
  5291.       Exit;
  5292.     end;
  5293.  
  5294.     BasicVideo2 := nil;
  5295.     try
  5296.       if (FVideoRenderer.QueryInterface(IID_IBasicVideo2, BasicVideo2) = S_OK) then
  5297.       begin
  5298.         BasicVideo2.SetDefaultSourcePosition;
  5299.         BasicVideo2.get_SourceLeft(SLeft);
  5300.         BasicVideo2.get_SourceTop(STop);
  5301.         BasicVideo2.get_SourceWidth(SWidth);
  5302.         BasicVideo2.get_SourceHeight(SHeight);
  5303.  
  5304.         Ratio := SHeight / SWidth;
  5305.  
  5306.         TmpX := SWidth - ((Value * Swidth) / 100);
  5307.         TmpY := TmpX * Ratio;
  5308.  
  5309.         TmpLeft := (SWidth - TmpX) / 2;
  5310.         TmpTop := (SHeight - TmpY) / 2;
  5311.  
  5312.         BasicVideo2.put_SourceWidth(Trunc(TmpX));
  5313.         BasicVideo2.put_SourceHeight(Trunc(TmpY));
  5314.         BasicVideo2.put_SourceLeft(Trunc(TmpLeft));
  5315.         BasicVideo2.put_SourceTop(Trunc(TmpTop));
  5316.       end;
  5317.       FZoom := Value;
  5318.     finally
  5319.       BasicVideo2 := nil;
  5320.     end;
  5321.   end;
  5322.  
  5323.   procedure TDSVideoWindowEx2.SetAspectMode(Value : TRatioModes);
  5324.   var
  5325.     input      : IPin;
  5326.     enum       : IEnumPins;
  5327.     pMPC       : IMixerPinConfig2;
  5328.   begin
  5329.     if (csDesigning in ComponentState) or (FVideoRenderer = nil) or (FOverlayMixer = nil) then
  5330.     begin
  5331.       FAspectMode := Value;
  5332.       Exit;
  5333.     end;
  5334.  
  5335.     try
  5336.       FOverlayMixer.EnumPins(Enum);
  5337.       Enum.Next(1, Input, nil);
  5338.  
  5339.       if Succeeded(Input.QueryInterface(IID_IMixerPinConfig2, pMPC)) then
  5340.         if Succeeded(pMPC.SetAspectRatioMode(TAMAspectRatioMode(integer(Value)))) then
  5341.           FAspectMode := Value;
  5342.     finally
  5343.       input := nil;
  5344.       enum  := nil;
  5345.       pMPC  := nil;
  5346.     end;
  5347.     if (GraphBuildOk) and (not FDesktopPlay) then Clearback;
  5348.   end;
  5349.  
  5350.   procedure TDSVideoWindowEx2.MouseDown(Button: TMouseButton;
  5351.     Shift: TShiftState; X, Y: Integer);
  5352.   Var
  5353.     MPos : TPoint;
  5354.   begin
  5355.     if Ffullscreen then
  5356.       MPos := Point(mouse.CursorPos.X, mouse.CursorPos.Y)
  5357.     else
  5358.       MPos := Point(X, Y);
  5359.  
  5360.     if FVideoWindow <> nil then
  5361.     begin
  5362.       if GraphBuildOK then
  5363.       begin
  5364.         if Self.Cursor = crnone then
  5365.         begin
  5366.           Self.Cursor := RememberCursor;
  5367.           LMousePos.X := MPos.X;
  5368.           LMousePos.Y := MPos.Y;
  5369.           LCursorMov := GetTickCount;
  5370.           if Assigned(FOnCursorVisible) then
  5371.             FOnCursorVisible(Self, True);
  5372.         end;
  5373.       end
  5374.       else
  5375.       begin
  5376.         FVideoWindow.IsCursorHidden(IsHidden);
  5377.         if IsHidden then
  5378.         begin
  5379.           FVideoWindow.HideCursor(False);
  5380.           LMousePos.X := MPos.X;
  5381.           LMousePos.Y := MPos.Y;
  5382.           LCursorMov := GetTickCount;
  5383.           IsHidden := False;
  5384.           if Assigned(FOnCursorVisible) then
  5385.             FOnCursorVisible(Self, True);
  5386.         end;
  5387.       end;
  5388.     end;
  5389.  
  5390.     inherited MouseDown(Button, Shift, MPos.X, MPos.Y);
  5391.   end;
  5392.  
  5393.   procedure TDSVideoWindowEx2.MouseMove(Shift: TShiftState; X, Y: Integer);
  5394.   var
  5395.     MPos : TPoint;
  5396.   begin
  5397.     if Ffullscreen then
  5398.       MPos := Point(mouse.CursorPos.X, mouse.CursorPos.Y)
  5399.     else
  5400.       MPos := Point(X, Y);
  5401.  
  5402.     if (LMousePos.X <> MPos.X) or (LMousePos.Y <> MPos.Y) then
  5403.     begin
  5404.       LMousePos.X := MPos.X;
  5405.       LMousePos.Y := MPos.Y;
  5406.       LCursorMov := GetTickCount;
  5407.       if FVideoWindow <> nil then
  5408.       begin
  5409.         if GraphBuildOk then
  5410.         begin
  5411.           if Self.Cursor = crnone then
  5412.           begin
  5413.             Self.Cursor := RememberCursor;
  5414.             if Assigned(FOnCursorVisible) then
  5415.               FOnCursorVisible(Self, True);
  5416.           end;
  5417.         end
  5418.         else
  5419.         begin
  5420.           FVideoWindow.IsCursorHidden(IsHidden);
  5421.           if IsHidden then
  5422.           begin
  5423.             FVideoWindow.HideCursor(False);
  5424.             IsHidden := False;
  5425.             if Assigned(FOnCursorVisible) then
  5426.               FOnCursorVisible(Self, True);
  5427.           end;
  5428.         end;
  5429.       end;
  5430.     end;
  5431.  
  5432.     inherited MouseMove(Shift, MPos.X, MPos.Y);
  5433.   end;
  5434.  
  5435.   procedure TDSVideoWindowEx2.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  5436.   var
  5437.     MPos : TPoint;
  5438.   begin
  5439.     if Ffullscreen then
  5440.       MPos := Point(mouse.CursorPos.X, mouse.CursorPos.Y)
  5441.     else
  5442.       MPos := Point(X, Y);
  5443.  
  5444.     if FVideoWindow <> nil then
  5445.     begin
  5446.       if GraphBuildOK then
  5447.       begin
  5448.         if Self.Cursor = crnone then
  5449.         begin
  5450.           Self.Cursor := RememberCursor;
  5451.           LMousePos.X := MPos.X;
  5452.           LMousePos.Y := MPos.Y;
  5453.           LCursorMov := GetTickCount;
  5454.           if Assigned(FOnCursorVisible) then
  5455.             FOnCursorVisible(Self, True);
  5456.         end;
  5457.       end
  5458.       else
  5459.       begin
  5460.         FVideoWindow.IsCursorHidden(IsHidden);
  5461.         if IsHidden then
  5462.         begin
  5463.           FVideoWindow.HideCursor(False);
  5464.           LMousePos.X := MPos.X;
  5465.           LMousePos.Y := MPos.Y;
  5466.           LCursorMov := GetTickCount;
  5467.           IsHidden := False;
  5468.           if Assigned(FOnCursorVisible) then
  5469.             FOnCursorVisible(Self, True);
  5470.         end;
  5471.       end;
  5472.     end;
  5473.     inherited MouseUp(Button, Shift, MPos.X, MPos.Y);
  5474.   end;
  5475.  
  5476.   procedure TDSVideoWindowEx2.MyIdleHandler(Sender: TObject; var Done: Boolean);
  5477.   var
  5478.     pt : TPoint;
  5479.   begin
  5480.     Done := True;
  5481.     if (FIdleCursor = 0) or (csDesigning in ComponentState) then exit;
  5482.     if (GetTickCount - LCursorMov >= Cardinal(FIdleCursor)) and (FVideoWindow <> nil) then
  5483.     begin
  5484.       if GraphBuildOK then
  5485.       begin
  5486.         if Self.Cursor <> crNone then
  5487.         begin
  5488.           RememberCursor := Self.Cursor;
  5489.           Self.Cursor := crNone;
  5490.           GetCursorPos(pt);
  5491.           SetCursorPos(pt.x, pt.y);
  5492.           if Assigned(FOnCursorVisible) then
  5493.             FOnCursorVisible(Self, False);
  5494.         end;
  5495.       end
  5496.       else
  5497.       begin
  5498.         FVideoWindow.IsCursorHidden(IsHidden);
  5499.         if not IsHidden then
  5500.         begin
  5501.           FVideoWindow.HideCursor(True);
  5502.           IsHidden := True;
  5503.           GetCursorPos(pt);
  5504.           SetCursorPos(pt.x, pt.y);
  5505.           if Assigned(FOnCursorVisible) then
  5506.             FOnCursorVisible(Self, False);
  5507.         end;
  5508.       end;
  5509.     end;
  5510.   end;
  5511.  
  5512. { TVMRBitmap }
  5513.  
  5514.   constructor TVMRBitmap.Create(VideoWindow: TVideoWindow);
  5515.   begin
  5516.     Assert(Assigned(VideoWindow),'No valid video Window.');
  5517.     FCanvas := TCanvas.Create;
  5518.     FVideoWindow := VideoWindow;
  5519.     FillChar(FVMRALPHABITMAP, SizeOf(FVMRALPHABITMAP), 0);
  5520.     Options := [];
  5521.     FVMRALPHABITMAP.hdc := 0;
  5522.     FVMRALPHABITMAP.fAlpha := 1;
  5523.   end;
  5524.  
  5525.   destructor TVMRBitmap.Destroy;
  5526.   begin
  5527.     ResetBitmap;
  5528.     FCanvas.Free;
  5529.   end;
  5530.  
  5531.   procedure TVMRBitmap.Draw;
  5532.   var VMRMixerBitmap: IVMRMixerBitmap9;
  5533.   begin
  5534.     if Succeeded(FVideoWindow.QueryInterface(IVMRMixerBitmap9, VMRMixerBitmap)) then
  5535.       VMRMixerBitmap.SetAlphaBitmap(@FVMRALPHABITMAP);
  5536.   end;
  5537.  
  5538.   procedure TVMRBitmap.DrawTo(Left, Top, Right, Bottom, Alpha: Single; doUpdate: boolean = false);
  5539.   begin
  5540.     with FVMRALPHABITMAP do
  5541.     begin
  5542.       rDest.left := Left;
  5543.       rDest.top := Top;
  5544.       rDest.right := Right;
  5545.       rDest.bottom := Bottom;
  5546.       fAlpha := Alpha;
  5547.     end;
  5548.     if doUpdate then Update else Draw;
  5549.   end;
  5550.  
  5551.   function TVMRBitmap.GetAlpha: Single;
  5552. begin
  5553.   result := FVMRALPHABITMAP.fAlpha;
  5554. end;
  5555.  
  5556. function TVMRBitmap.GetColorKey: COLORREF;
  5557. begin
  5558.   Result := FVMRALPHABITMAP.clrSrcKey;
  5559. end;
  5560.  
  5561. function TVMRBitmap.GetDest: TVMR9NormalizedRect;
  5562. begin
  5563.   Result := FVMRALPHABITMAP.rDest;
  5564. end;
  5565.  
  5566. function TVMRBitmap.GetDestBottom: Single;
  5567. begin
  5568.   Result := FVMRALPHABITMAP.rDest.bottom;
  5569. end;
  5570.  
  5571. function TVMRBitmap.GetDestLeft: Single;
  5572. begin
  5573.   Result := FVMRALPHABITMAP.rDest.Left;
  5574. end;
  5575.  
  5576. function TVMRBitmap.GetDestRight: Single;
  5577. begin
  5578.  Result := FVMRALPHABITMAP.rDest.right
  5579. end;
  5580.  
  5581. function TVMRBitmap.GetDestTop: Single;
  5582. begin
  5583.   Result := FVMRALPHABITMAP.rDest.top;
  5584. end;
  5585.  
  5586. function TVMRBitmap.GetSource: TRect;
  5587. begin
  5588.   result := FVMRALPHABITMAP.rSrc;
  5589. end;
  5590.  
  5591. procedure TVMRBitmap.LoadBitmap(Bitmap: TBitmap);
  5592. var
  5593.   TmpHDC, HdcBMP: HDC;
  5594.   BMP: Windows.TBITMAP;
  5595. begin
  5596.   Assert(Assigned(Bitmap),'Invalid Bitmap.');
  5597.   ResetBitmap;
  5598.   TmpHDC := GetDC(FVideoWindow.Handle);
  5599.   if (TmpHDC = 0) then Exit;
  5600.   HdcBMP := CreateCompatibleDC(TmpHDC);
  5601.   ReleaseDC(FVideoWindow.Handle, TmpHDC);
  5602.   if (HdcBMP = 0) then Exit;
  5603.   if (0 = GetObject(Bitmap.Handle, sizeof(BMP), @BMP)) then exit;
  5604.   FBMPOld := SelectObject(HdcBMP, Bitmap.Handle);
  5605.   if (FBMPOld = 0) then Exit;
  5606.   FVMRALPHABITMAP.hdc := HdcBMP;
  5607.   FCanvas.Handle := HdcBMP;
  5608. end;
  5609.  
  5610. procedure TVMRBitmap.LoadEmptyBitmap(Width, Height: Integer;
  5611.   PixelFormat: TPixelFormat; Color: TColor);
  5612. var Bitmap: TBitmap;
  5613. begin
  5614.   Bitmap := TBitmap.Create;
  5615.   try
  5616.     Bitmap.Width := Width;
  5617.     Bitmap.Height := Height;
  5618.     Bitmap.PixelFormat := PixelFormat;
  5619.     Bitmap.Canvas.Brush.Color := Color;
  5620.     Bitmap.Canvas.FillRect(Bitmap.Canvas.ClipRect);
  5621.     LoadBitmap(Bitmap);
  5622.   finally
  5623.     Bitmap.Free;
  5624.   end;
  5625. end;
  5626.  
  5627. procedure TVMRBitmap.ResetBitmap;
  5628. begin
  5629.   FCanvas.Handle := 0;
  5630.   if FVMRALPHABITMAP.hdc <> 0 then
  5631.   begin
  5632.     DeleteObject(SelectObject(FVMRALPHABITMAP.hdc, FBMPOld));
  5633.     DeleteDC(FVMRALPHABITMAP.hdc);
  5634.     FVMRALPHABITMAP.hdc := 0;
  5635.   end;
  5636. end;
  5637.  
  5638. procedure TVMRBitmap.SetAlpha(const Value: Single);
  5639. begin
  5640.   FVMRALPHABITMAP.fAlpha := Value;
  5641. end;
  5642.  
  5643. procedure TVMRBitmap.SetColorKey(const Value: COLORREF);
  5644. begin
  5645.   FVMRALPHABITMAP.clrSrcKey := Value;
  5646. end;
  5647.  
  5648. procedure TVMRBitmap.SetDest(const Value: TVMR9NormalizedRect);
  5649. begin
  5650.   FVMRALPHABITMAP.rDest := Value;
  5651. end;
  5652.  
  5653. procedure TVMRBitmap.SetDestBottom(const Value: Single);
  5654. begin
  5655.   FVMRALPHABITMAP.rDest.bottom := Value;
  5656. end;
  5657.  
  5658. procedure TVMRBitmap.SetDestLeft(const Value: Single);
  5659. begin
  5660.   FVMRALPHABITMAP.rDest.Left := Value;
  5661. end;
  5662.  
  5663. procedure TVMRBitmap.SetDestRight(const Value: Single);
  5664. begin
  5665.   FVMRALPHABITMAP.rDest.right := Value;
  5666. end;
  5667.  
  5668. procedure TVMRBitmap.SetDestTop(const Value: Single);
  5669. begin
  5670.   FVMRALPHABITMAP.rDest.top := Value;
  5671. end;
  5672.  
  5673. procedure TVMRBitmap.SetOptions(Options: TVMRBitmapOptions);
  5674. begin
  5675.   FOptions := Options;
  5676.   FVMRALPHABITMAP.dwFlags := VMR9AlphaBitmap_hDC;
  5677.   if vmrbDisable in Options then FVMRALPHABITMAP.dwFlags := FVMRALPHABITMAP.dwFlags or VMR9AlphaBitmap_Disable;
  5678.   if vmrbSrcColorKey in Options then FVMRALPHABITMAP.dwFlags := FVMRALPHABITMAP.dwFlags or VMR9AlphaBitmap_SrcColorKey;
  5679.   if vmrbSrcRect in Options then FVMRALPHABITMAP.dwFlags := FVMRALPHABITMAP.dwFlags or VMR9AlphaBitmap_SrcRect;
  5680. end;
  5681.  
  5682. procedure TVMRBitmap.SetSource(const Value: TRect);
  5683. begin
  5684.   FVMRALPHABITMAP.rSrc := Value;
  5685. end;
  5686.  
  5687. procedure TVMRBitmap.Update;
  5688.   var VMRMixerBitmap: IVMRMixerBitmap9;
  5689.   begin
  5690.     if Succeeded(FVideoWindow.QueryInterface(IVMRMixerBitmap9, VMRMixerBitmap)) then
  5691.       VMRMixerBitmap.UpdateAlphaBitmapParameters(@FVMRALPHABITMAP);
  5692.   end;
  5693.  
  5694. end.
  5695.  
  5696.  
  5697.